mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-01 19:48:38 +08:00
Refactor upload (#5290)
* refactor: vc-upload * refactor: vc-upload * refactor: upload * refactor: upload * refactor: upload
This commit is contained in:
parent
3cf5d4fa43
commit
04baae5a57
@ -224,7 +224,7 @@ export {
|
||||
TypographyTitle,
|
||||
} from './typography';
|
||||
|
||||
export type { UploadProps, UploadListProps, UploadChangeParam } from './upload';
|
||||
export type { UploadProps, UploadListProps, UploadChangeParam, UploadFile } from './upload';
|
||||
|
||||
export { default as Upload, UploadDragger } from './upload';
|
||||
|
||||
|
@ -1535,8 +1535,10 @@ exports[`renders ./components/form/demo/validate-other.vue correctly 1`] = `
|
||||
</label></div>
|
||||
<div class="ant-col ant-col-14 ant-form-item-control">
|
||||
<div class="ant-form-item-control-input">
|
||||
<div class="ant-form-item-control-input-content"><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span role="button" tabindex="0" class="ant-upload"><input id="validate_other_upload" type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture"></div></span>
|
||||
<div class="ant-form-item-control-input-content"><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input id="validate_other_upload" type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<!---->
|
||||
</div></span>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
@ -1550,17 +1552,18 @@ exports[`renders ./components/form/demo/validate-other.vue correctly 1`] = `
|
||||
</label></div>
|
||||
<div class="ant-col ant-col-14 ant-form-item-control">
|
||||
<div class="ant-form-item-control-input">
|
||||
<div class="ant-form-item-control-input-content"><span><div class="ant-upload ant-upload-drag"><span role="button" tabindex="0" class="ant-upload ant-upload-btn"><input id="validate_other_dragger" type="file" style="display: none;" accept=""><div class="ant-upload-drag-container"><p class="ant-upload-drag-icon"><span role="img" aria-label="inbox" class="anticon anticon-inbox"><svg focusable="false" class="" data-icon="inbox" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"></path></svg></span></p>
|
||||
<div class="ant-form-item-control-input-content"><span><div class="ant-upload ant-upload-drag"><span tabindex="0" class="ant-upload ant-upload-btn" role="button"><input id="validate_other_dragger" type="file" style="display: none;" accept="" capture="false"><p class="ant-upload-drag-icon"><span role="img" aria-label="inbox" class="anticon anticon-inbox"><svg focusable="false" class="" data-icon="inbox" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"></path></svg></span></p>
|
||||
<p class="ant-upload-text">Click or drag file to this area to upload</p>
|
||||
<p class="ant-upload-hint">Support for a single or bulk upload.</p>
|
||||
<p class="ant-upload-hint">Support for a single or bulk upload.</p></span>
|
||||
</div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<!---->
|
||||
</div></span>
|
||||
</div>
|
||||
<div class="ant-upload-list ant-upload-list-text"></div></span>
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-row ant-form-item">
|
||||
|
@ -9,6 +9,7 @@ import type { TransferLocale } from '../transfer';
|
||||
import type { PickerLocale as DatePickerLocale } from '../date-picker/generatePicker';
|
||||
import type { PaginationLocale } from '../pagination/Pagination';
|
||||
import type { TableLocale } from '../table/interface';
|
||||
import type { UploadLocale } from '../upload/interface';
|
||||
|
||||
interface TransferLocaleForEmpty {
|
||||
description: string;
|
||||
@ -18,7 +19,6 @@ export interface Locale {
|
||||
Pagination?: PaginationLocale;
|
||||
Table?: TableLocale;
|
||||
Popconfirm?: Record<string, any>;
|
||||
Upload?: Record<string, any>;
|
||||
Form?: {
|
||||
optional?: string;
|
||||
defaultValidateMessages: ValidateMessages;
|
||||
@ -32,6 +32,7 @@ export interface Locale {
|
||||
Modal?: ModalLocale;
|
||||
Transfer?: Partial<TransferLocale>;
|
||||
Select?: Record<string, any>;
|
||||
Upload?: UploadLocale;
|
||||
Empty?: TransferLocaleForEmpty;
|
||||
global?: Record<string, any>;
|
||||
PageHeader?: { back: string };
|
||||
|
@ -61,8 +61,10 @@ exports[`renders ./components/space/demo/base.vue correctly 1`] = `
|
||||
<!----><span>Button</span>
|
||||
</button></div>
|
||||
<!---->
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text"></div></span>
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<!---->
|
||||
</div></span>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="ant-space-item">
|
||||
|
@ -965,6 +965,10 @@
|
||||
@typography-title-margin-top: 1.2em;
|
||||
@typography-title-margin-bottom: 0.5em;
|
||||
|
||||
// Upload
|
||||
// ---
|
||||
@upload-actions-color: @text-color-secondary;
|
||||
|
||||
// Image
|
||||
// ---
|
||||
@image-size-base: 48px;
|
||||
|
@ -1,22 +1,22 @@
|
||||
import { defineComponent } from 'vue';
|
||||
import { getOptionProps, getSlot } from '../_util/props-util';
|
||||
import Upload from './Upload';
|
||||
import { uploadProps } from './interface';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AUploadDragger',
|
||||
inheritAttrs: false,
|
||||
props: uploadProps,
|
||||
render() {
|
||||
const props = getOptionProps(this);
|
||||
const { height, ...restProps } = props;
|
||||
const { style, ...restAttrs } = this.$attrs;
|
||||
const draggerProps = {
|
||||
...restProps,
|
||||
...restAttrs,
|
||||
type: 'drag',
|
||||
style: { ...(style as any), height },
|
||||
} as any;
|
||||
return <Upload {...draggerProps}>{getSlot(this)}</Upload>;
|
||||
props: uploadProps(),
|
||||
setup(props, { slots, attrs }) {
|
||||
return () => {
|
||||
const { height, ...restProps } = props;
|
||||
const { style, ...restAttrs } = attrs;
|
||||
const draggerProps = {
|
||||
...restProps,
|
||||
...restAttrs,
|
||||
type: 'drag',
|
||||
style: { ...(style as any), height: typeof height === 'number' ? `${height}px` : height },
|
||||
} as any;
|
||||
return <Upload {...draggerProps} v-slots={slots}></Upload>;
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -1,86 +1,196 @@
|
||||
import classNames from '../_util/classNames';
|
||||
import uniqBy from 'lodash-es/uniqBy';
|
||||
import findIndex from 'lodash-es/findIndex';
|
||||
import type { UploadProps as RcUploadProps } from '../vc-upload';
|
||||
import VcUpload from '../vc-upload';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import { getOptionProps, hasProp, getSlot } from '../_util/props-util';
|
||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import defaultLocale from '../locale-provider/default';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import Dragger from './Dragger';
|
||||
import UploadList from './UploadList';
|
||||
import type { UploadFile } from './interface';
|
||||
import type {
|
||||
UploadType,
|
||||
UploadListType,
|
||||
UploadFile,
|
||||
UploadChangeParam,
|
||||
ShowUploadListInterface,
|
||||
FileType,
|
||||
} from './interface';
|
||||
import { uploadProps } from './interface';
|
||||
import { T, fileToObject, genPercentAdd, getFileItem, removeFileItem } from './utils';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { getDataAndAriaProps } from '../_util/util';
|
||||
import { useInjectFormItemContext } from '../form/FormItemContext';
|
||||
import { file2Obj, getFileItem, removeFileItem, updateFileList } from './utils';
|
||||
import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
|
||||
import defaultLocale from '../locale/default';
|
||||
import { computed, defineComponent, onMounted, ref, toRef } from 'vue';
|
||||
import { flattenChildren, initDefaultProps } from '../_util/props-util';
|
||||
import useMergedState from '../_util/hooks/useMergedState';
|
||||
import devWarning from '../vc-util/devWarning';
|
||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||
import type { VueNode } from '../_util/type';
|
||||
import classNames from '../_util/classNames';
|
||||
import { useInjectFormItemContext } from '../form';
|
||||
|
||||
export const LIST_IGNORE = `__LIST_IGNORE_${Date.now()}__`;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AUpload',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
Dragger,
|
||||
props: initDefaultProps(uploadProps, {
|
||||
type: 'select',
|
||||
props: initDefaultProps(uploadProps(), {
|
||||
type: 'select' as UploadType,
|
||||
multiple: false,
|
||||
action: '',
|
||||
data: {},
|
||||
accept: '',
|
||||
beforeUpload: T,
|
||||
showUploadList: true,
|
||||
listType: 'text', // or pictrue
|
||||
listType: 'text' as UploadListType, // or picture
|
||||
disabled: false,
|
||||
supportServerRender: true,
|
||||
}),
|
||||
setup() {
|
||||
setup(props, { slots, attrs, expose }) {
|
||||
const formItemContext = useInjectFormItemContext();
|
||||
return {
|
||||
upload: null,
|
||||
progressTimer: null,
|
||||
configProvider: inject('configProvider', defaultConfigProvider),
|
||||
formItemContext,
|
||||
};
|
||||
},
|
||||
// recentUploadStatus: boolean | PromiseLike<any>;
|
||||
data() {
|
||||
return {
|
||||
sFileList: this.fileList || this.defaultFileList || [],
|
||||
dragState: 'drop',
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
fileList(val) {
|
||||
this.sFileList = val || [];
|
||||
},
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.clearProgressTimer();
|
||||
},
|
||||
methods: {
|
||||
onStart(file) {
|
||||
const targetItem = fileToObject(file);
|
||||
targetItem.status = 'uploading';
|
||||
const nextFileList = this.sFileList.concat();
|
||||
const fileIndex = findIndex(nextFileList, ({ uid }) => uid === targetItem.uid);
|
||||
if (fileIndex === -1) {
|
||||
nextFileList.push(targetItem);
|
||||
} else {
|
||||
nextFileList[fileIndex] = targetItem;
|
||||
}
|
||||
this.handleChange({
|
||||
file: targetItem,
|
||||
fileList: nextFileList,
|
||||
});
|
||||
// fix ie progress
|
||||
if (!window.File || (typeof process === 'object' && process.env.TEST_IE)) {
|
||||
this.autoUpdateProgress(0, targetItem);
|
||||
}
|
||||
},
|
||||
const [mergedFileList, setMergedFileList] = useMergedState(props.defaultFileList || [], {
|
||||
value: toRef(props, 'fileList'),
|
||||
postState: list => {
|
||||
const timestamp = Date.now();
|
||||
return (list ?? []).map((file, index) => {
|
||||
if (!file.uid && !Object.isFrozen(file)) {
|
||||
file.uid = `__AUTO__${timestamp}_${index}__`;
|
||||
}
|
||||
return file;
|
||||
});
|
||||
},
|
||||
});
|
||||
const dragState = ref('drop');
|
||||
|
||||
onSuccess(response, file, xhr) {
|
||||
this.clearProgressTimer();
|
||||
const upload = ref();
|
||||
onMounted(() => {
|
||||
devWarning(
|
||||
props.fileList !== undefined || attrs.value === undefined,
|
||||
'Upload',
|
||||
'`value` is not a valid prop, do you mean `fileList`?',
|
||||
);
|
||||
|
||||
devWarning(
|
||||
props.transformFile === undefined,
|
||||
'Upload',
|
||||
'`transformFile` is deprecated. Please use `beforeUpload` directly.',
|
||||
);
|
||||
devWarning(
|
||||
props.remove === undefined,
|
||||
'Upload',
|
||||
'`remove` props is deprecated. Please use `remove` event.',
|
||||
);
|
||||
});
|
||||
|
||||
const onInternalChange = (
|
||||
file: UploadFile,
|
||||
changedFileList: UploadFile[],
|
||||
event?: { percent: number },
|
||||
) => {
|
||||
let cloneList = [...changedFileList];
|
||||
|
||||
// Cut to match count
|
||||
if (props.maxCount === 1) {
|
||||
cloneList = cloneList.slice(-1);
|
||||
} else if (props.maxCount) {
|
||||
cloneList = cloneList.slice(0, props.maxCount);
|
||||
}
|
||||
|
||||
setMergedFileList(cloneList);
|
||||
|
||||
const changeInfo: UploadChangeParam<UploadFile> = {
|
||||
file: file as UploadFile,
|
||||
fileList: cloneList,
|
||||
};
|
||||
|
||||
if (event) {
|
||||
changeInfo.event = event;
|
||||
}
|
||||
props['onUpdate:fileList']?.(changeInfo.fileList);
|
||||
props.onChange?.(changeInfo);
|
||||
formItemContext.onFieldChange();
|
||||
};
|
||||
|
||||
const mergedBeforeUpload = async (file: FileType, fileListArgs: FileType[]) => {
|
||||
const { beforeUpload, transformFile } = props;
|
||||
|
||||
let parsedFile: FileType | Blob | string = file;
|
||||
if (beforeUpload) {
|
||||
const result = await beforeUpload(file, fileListArgs);
|
||||
|
||||
if (result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hack for LIST_IGNORE, we add additional info to remove from the list
|
||||
delete (file as any)[LIST_IGNORE];
|
||||
if ((result as any) === LIST_IGNORE) {
|
||||
Object.defineProperty(file, LIST_IGNORE, {
|
||||
value: true,
|
||||
configurable: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof result === 'object' && result) {
|
||||
parsedFile = result as File;
|
||||
}
|
||||
}
|
||||
|
||||
if (transformFile) {
|
||||
parsedFile = await transformFile(parsedFile as any);
|
||||
}
|
||||
|
||||
return parsedFile as File;
|
||||
};
|
||||
|
||||
const onBatchStart: RcUploadProps['onBatchStart'] = batchFileInfoList => {
|
||||
// Skip file which marked as `LIST_IGNORE`, these file will not add to file list
|
||||
const filteredFileInfoList = batchFileInfoList.filter(
|
||||
info => !(info.file as any)[LIST_IGNORE],
|
||||
);
|
||||
|
||||
// Nothing to do since no file need upload
|
||||
if (!filteredFileInfoList.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const objectFileList = filteredFileInfoList.map(info => file2Obj(info.file as FileType));
|
||||
|
||||
// Concat new files with prev files
|
||||
let newFileList = [...mergedFileList.value];
|
||||
|
||||
objectFileList.forEach(fileObj => {
|
||||
// Replace file if exist
|
||||
newFileList = updateFileList(fileObj, newFileList);
|
||||
});
|
||||
|
||||
objectFileList.forEach((fileObj, index) => {
|
||||
// Repeat trigger `onChange` event for compatible
|
||||
let triggerFileObj: UploadFile = fileObj;
|
||||
|
||||
if (!filteredFileInfoList[index].parsedFile) {
|
||||
// `beforeUpload` return false
|
||||
const { originFileObj } = fileObj;
|
||||
let clone;
|
||||
|
||||
try {
|
||||
clone = new File([originFileObj], originFileObj.name, {
|
||||
type: originFileObj.type,
|
||||
}) as any as UploadFile;
|
||||
} catch (e) {
|
||||
clone = new Blob([originFileObj], {
|
||||
type: originFileObj.type,
|
||||
}) as any as UploadFile;
|
||||
clone.name = originFileObj.name;
|
||||
clone.lastModifiedDate = new Date();
|
||||
clone.lastModified = new Date().getTime();
|
||||
}
|
||||
|
||||
clone.uid = fileObj.uid;
|
||||
triggerFileObj = clone;
|
||||
} else {
|
||||
// Inject `uploading` status
|
||||
fileObj.status = 'uploading';
|
||||
}
|
||||
|
||||
onInternalChange(triggerFileObj, newFileList);
|
||||
});
|
||||
};
|
||||
|
||||
const onSuccess = (response: any, file: FileType, xhr: any) => {
|
||||
try {
|
||||
if (typeof response === 'string') {
|
||||
response = JSON.parse(response);
|
||||
@ -88,255 +198,233 @@ export default defineComponent({
|
||||
} catch (e) {
|
||||
/* do nothing */
|
||||
}
|
||||
const fileList = this.sFileList;
|
||||
const targetItem = getFileItem(file, fileList);
|
||||
|
||||
// removed
|
||||
if (!targetItem) {
|
||||
if (!getFileItem(file, mergedFileList.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetItem = file2Obj(file);
|
||||
targetItem.status = 'done';
|
||||
targetItem.percent = 100;
|
||||
targetItem.response = response;
|
||||
targetItem.xhr = xhr;
|
||||
this.handleChange({
|
||||
file: { ...targetItem },
|
||||
fileList,
|
||||
});
|
||||
},
|
||||
onProgress(e, file) {
|
||||
const fileList = this.sFileList;
|
||||
const targetItem = getFileItem(file, fileList);
|
||||
|
||||
const nextFileList = updateFileList(targetItem, mergedFileList.value);
|
||||
|
||||
onInternalChange(targetItem, nextFileList);
|
||||
};
|
||||
|
||||
const onProgress = (e: { percent: number }, file: FileType) => {
|
||||
// removed
|
||||
if (!targetItem) {
|
||||
if (!getFileItem(file, mergedFileList.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetItem = file2Obj(file);
|
||||
targetItem.status = 'uploading';
|
||||
targetItem.percent = e.percent;
|
||||
this.handleChange({
|
||||
event: e,
|
||||
file: { ...targetItem },
|
||||
fileList: this.sFileList,
|
||||
});
|
||||
},
|
||||
onError(error, response, file) {
|
||||
this.clearProgressTimer();
|
||||
const fileList = this.sFileList;
|
||||
const targetItem = getFileItem(file, fileList);
|
||||
|
||||
const nextFileList = updateFileList(targetItem, mergedFileList.value);
|
||||
|
||||
onInternalChange(targetItem, nextFileList, e);
|
||||
};
|
||||
|
||||
const onError = (error: Error, response: any, file: FileType) => {
|
||||
// removed
|
||||
if (!targetItem) {
|
||||
if (!getFileItem(file, mergedFileList.value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetItem = file2Obj(file);
|
||||
targetItem.error = error;
|
||||
targetItem.response = response;
|
||||
targetItem.status = 'error';
|
||||
this.handleChange({
|
||||
file: { ...targetItem },
|
||||
fileList,
|
||||
});
|
||||
},
|
||||
onReject(fileList) {
|
||||
this.$emit('reject', fileList);
|
||||
},
|
||||
handleRemove(file) {
|
||||
const { remove: onRemove } = this;
|
||||
const { sFileList: fileList } = this.$data;
|
||||
|
||||
Promise.resolve(typeof onRemove === 'function' ? onRemove(file) : onRemove).then(ret => {
|
||||
// Prevent removing file
|
||||
if (ret === false) {
|
||||
return;
|
||||
}
|
||||
const nextFileList = updateFileList(targetItem, mergedFileList.value);
|
||||
|
||||
const removedFileList = removeFileItem(file, fileList);
|
||||
|
||||
if (removedFileList) {
|
||||
file.status = 'removed'; // eslint-disable-line
|
||||
|
||||
if (this.upload) {
|
||||
this.upload.abort(file);
|
||||
}
|
||||
|
||||
this.handleChange({
|
||||
file,
|
||||
fileList: removedFileList,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
handleManualRemove(file) {
|
||||
if (this.$refs.uploadRef) {
|
||||
(this.$refs.uploadRef as any).abort(file);
|
||||
}
|
||||
this.handleRemove(file);
|
||||
},
|
||||
handleChange(info) {
|
||||
if (!hasProp(this, 'fileList')) {
|
||||
this.setState({ sFileList: info.fileList });
|
||||
}
|
||||
this.$emit('update:fileList', info.fileList);
|
||||
this.$emit('change', info);
|
||||
this.formItemContext.onFieldChange();
|
||||
},
|
||||
onFileDrop(e) {
|
||||
this.setState({
|
||||
dragState: e.type,
|
||||
});
|
||||
},
|
||||
reBeforeUpload(file, fileList) {
|
||||
const { beforeUpload } = this.$props;
|
||||
const { sFileList: stateFileList } = this.$data;
|
||||
if (!beforeUpload) {
|
||||
return true;
|
||||
}
|
||||
const result = beforeUpload(file, fileList);
|
||||
if (result === false) {
|
||||
this.handleChange({
|
||||
file,
|
||||
fileList: uniqBy(
|
||||
stateFileList.concat(fileList.map(fileToObject)),
|
||||
(item: UploadFile) => item.uid,
|
||||
),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (result && result.then) {
|
||||
return result;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
clearProgressTimer() {
|
||||
clearInterval(this.progressTimer);
|
||||
},
|
||||
autoUpdateProgress(_, file) {
|
||||
const getPercent = genPercentAdd();
|
||||
let curPercent = 0;
|
||||
this.clearProgressTimer();
|
||||
this.progressTimer = setInterval(() => {
|
||||
curPercent = getPercent(curPercent);
|
||||
this.onProgress(
|
||||
{
|
||||
percent: curPercent * 100,
|
||||
},
|
||||
file,
|
||||
);
|
||||
}, 200);
|
||||
},
|
||||
renderUploadList(locale) {
|
||||
const {
|
||||
showUploadList = {},
|
||||
listType,
|
||||
previewFile,
|
||||
disabled,
|
||||
locale: propLocale,
|
||||
} = getOptionProps(this);
|
||||
const { showRemoveIcon, showPreviewIcon, showDownloadIcon } = showUploadList;
|
||||
const { sFileList: fileList } = this.$data;
|
||||
const { onDownload, onPreview } = this.$props;
|
||||
const uploadListProps = {
|
||||
listType,
|
||||
items: fileList,
|
||||
previewFile,
|
||||
showRemoveIcon: !disabled && showRemoveIcon,
|
||||
showPreviewIcon,
|
||||
showDownloadIcon,
|
||||
locale: { ...locale, ...propLocale },
|
||||
onRemove: this.handleManualRemove,
|
||||
onDownload,
|
||||
onPreview,
|
||||
};
|
||||
return <UploadList {...uploadListProps} />;
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
showUploadList,
|
||||
listType,
|
||||
type,
|
||||
disabled,
|
||||
} = getOptionProps(this);
|
||||
const { sFileList: fileList, dragState } = this.$data;
|
||||
const { class: className, style } = this.$attrs;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('upload', customizePrefixCls);
|
||||
|
||||
const vcUploadProps = {
|
||||
...this.$props,
|
||||
id: this.$props.id ?? this.formItemContext.id.value,
|
||||
prefixCls,
|
||||
beforeUpload: this.reBeforeUpload,
|
||||
onStart: this.onStart,
|
||||
onError: this.onError,
|
||||
onProgress: this.onProgress,
|
||||
onSuccess: this.onSuccess,
|
||||
onReject: this.onReject,
|
||||
ref: 'uploadRef',
|
||||
onInternalChange(targetItem, nextFileList);
|
||||
};
|
||||
|
||||
const uploadList = showUploadList ? (
|
||||
<LocaleReceiver
|
||||
componentName="Upload"
|
||||
defaultLocale={defaultLocale.Upload}
|
||||
children={this.renderUploadList}
|
||||
/>
|
||||
) : null;
|
||||
const handleRemove = (file: UploadFile) => {
|
||||
let currentFile: UploadFile;
|
||||
const mergedRemove = props.onRemove || props.remove;
|
||||
Promise.resolve(typeof mergedRemove === 'function' ? mergedRemove(file) : mergedRemove).then(
|
||||
ret => {
|
||||
// Prevent removing file
|
||||
if (ret === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const children = getSlot(this);
|
||||
const removedFileList = removeFileItem(file, mergedFileList.value);
|
||||
|
||||
if (type === 'drag') {
|
||||
const dragCls = classNames(prefixCls, {
|
||||
[`${prefixCls}-drag`]: true,
|
||||
[`${prefixCls}-drag-uploading`]: fileList.some((file: any) => file.status === 'uploading'),
|
||||
[`${prefixCls}-drag-hover`]: dragState === 'dragover',
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
});
|
||||
return (
|
||||
<span class={className} {...getDataAndAriaProps(this.$attrs)}>
|
||||
<div
|
||||
class={dragCls}
|
||||
onDrop={this.onFileDrop}
|
||||
onDragover={this.onFileDrop}
|
||||
onDragleave={this.onFileDrop}
|
||||
style={style}
|
||||
>
|
||||
<VcUpload {...vcUploadProps} class={`${prefixCls}-btn`}>
|
||||
<div class={`${prefixCls}-drag-container`}>{children}</div>
|
||||
</VcUpload>
|
||||
</div>
|
||||
{uploadList}
|
||||
</span>
|
||||
if (removedFileList) {
|
||||
currentFile = { ...file, status: 'removed' };
|
||||
mergedFileList.value?.forEach(item => {
|
||||
const matchKey = currentFile.uid !== undefined ? 'uid' : 'name';
|
||||
if (item[matchKey] === currentFile[matchKey] && !Object.isFrozen(item)) {
|
||||
item.status = 'removed';
|
||||
}
|
||||
});
|
||||
upload.value?.abort(currentFile);
|
||||
|
||||
onInternalChange(currentFile, removedFileList);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const uploadButtonCls = classNames(prefixCls, {
|
||||
[`${prefixCls}-select`]: true,
|
||||
[`${prefixCls}-select-${listType}`]: true,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
const onFileDrop = (e: DragEvent) => {
|
||||
dragState.value = e.type;
|
||||
if (e.type === 'drop') {
|
||||
props.onDrop?.(e);
|
||||
}
|
||||
};
|
||||
expose({
|
||||
onBatchStart,
|
||||
onSuccess,
|
||||
onProgress,
|
||||
onError,
|
||||
fileList: mergedFileList,
|
||||
upload,
|
||||
});
|
||||
|
||||
// Remove id to avoid open by label when trigger is hidden
|
||||
// https://github.com/ant-design/ant-design/issues/14298
|
||||
if (!children.length || disabled) {
|
||||
delete vcUploadProps.id;
|
||||
}
|
||||
|
||||
const uploadButton = (
|
||||
<div class={uploadButtonCls} style={children.length ? undefined : { display: 'none' }}>
|
||||
<VcUpload {...vcUploadProps}>{children}</VcUpload>
|
||||
</div>
|
||||
const { prefixCls, direction } = useConfigInject('upload', props);
|
||||
const [locale] = useLocaleReceiver(
|
||||
'Upload',
|
||||
defaultLocale.Upload,
|
||||
computed(() => props.locale),
|
||||
);
|
||||
const renderUploadList = (button?: VueNode) => {
|
||||
const {
|
||||
removeIcon,
|
||||
previewIcon,
|
||||
downloadIcon,
|
||||
previewFile,
|
||||
onPreview,
|
||||
onDownload,
|
||||
disabled,
|
||||
isImageUrl,
|
||||
progress,
|
||||
itemRender,
|
||||
iconRender,
|
||||
showUploadList,
|
||||
} = props;
|
||||
const { showDownloadIcon, showPreviewIcon, showRemoveIcon } =
|
||||
typeof showUploadList === 'boolean' ? ({} as ShowUploadListInterface) : showUploadList;
|
||||
return showUploadList ? (
|
||||
<UploadList
|
||||
listType={props.listType}
|
||||
items={mergedFileList.value}
|
||||
previewFile={previewFile}
|
||||
onPreview={onPreview}
|
||||
onDownload={onDownload}
|
||||
onRemove={handleRemove}
|
||||
showRemoveIcon={!disabled && showRemoveIcon}
|
||||
showPreviewIcon={showPreviewIcon}
|
||||
showDownloadIcon={showDownloadIcon}
|
||||
removeIcon={removeIcon}
|
||||
previewIcon={previewIcon}
|
||||
downloadIcon={downloadIcon}
|
||||
iconRender={iconRender}
|
||||
locale={locale.value}
|
||||
isImageUrl={isImageUrl}
|
||||
progress={progress}
|
||||
itemRender={itemRender}
|
||||
v-slots={{ ...slots, appendAction: () => button }}
|
||||
/>
|
||||
) : (
|
||||
button
|
||||
);
|
||||
};
|
||||
return () => {
|
||||
const { listType, disabled, type } = props;
|
||||
const rcUploadProps = {
|
||||
onBatchStart,
|
||||
onError,
|
||||
onProgress,
|
||||
onSuccess,
|
||||
...(props as RcUploadProps),
|
||||
id: props.id ?? formItemContext.id.value,
|
||||
prefixCls: prefixCls.value,
|
||||
beforeUpload: mergedBeforeUpload,
|
||||
onChange: undefined,
|
||||
};
|
||||
delete (rcUploadProps as any).remove;
|
||||
|
||||
if (listType === 'picture-card') {
|
||||
// Remove id to avoid open by label when trigger is hidden
|
||||
// !children: https://github.com/ant-design/ant-design/issues/14298
|
||||
// disabled: https://github.com/ant-design/ant-design/issues/16478
|
||||
// https://github.com/ant-design/ant-design/issues/24197
|
||||
if (!slots.default || disabled) {
|
||||
delete rcUploadProps.id;
|
||||
}
|
||||
if (type === 'drag') {
|
||||
const dragCls = classNames(
|
||||
prefixCls.value,
|
||||
{
|
||||
[`${prefixCls.value}-drag`]: true,
|
||||
[`${prefixCls.value}-drag-uploading`]: mergedFileList.value.some(
|
||||
file => file.status === 'uploading',
|
||||
),
|
||||
[`${prefixCls.value}-drag-hover`]: dragState.value === 'dragover',
|
||||
[`${prefixCls.value}-disabled`]: disabled,
|
||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||
},
|
||||
attrs.class,
|
||||
);
|
||||
return (
|
||||
<span>
|
||||
<div
|
||||
class={dragCls}
|
||||
onDrop={onFileDrop}
|
||||
onDragover={onFileDrop}
|
||||
onDragleave={onFileDrop}
|
||||
style={attrs.style}
|
||||
>
|
||||
<VcUpload
|
||||
{...rcUploadProps}
|
||||
ref={upload}
|
||||
class={`${prefixCls.value}-btn`}
|
||||
v-slots={slots}
|
||||
>
|
||||
<div class={`${prefixCls}-drag-container`}>{slots.default?.()}</div>
|
||||
</VcUpload>
|
||||
</div>
|
||||
{renderUploadList()}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const uploadButtonCls = classNames(prefixCls.value, {
|
||||
[`${prefixCls.value}-select`]: true,
|
||||
[`${prefixCls.value}-select-${listType}`]: true,
|
||||
[`${prefixCls.value}-disabled`]: disabled,
|
||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||
});
|
||||
const children = flattenChildren(slots.default?.());
|
||||
const uploadButton = (
|
||||
<div
|
||||
class={uploadButtonCls}
|
||||
style={children && children.length ? undefined : { display: 'none' }}
|
||||
>
|
||||
<VcUpload {...rcUploadProps} ref={upload} v-slots={slots} />
|
||||
</div>
|
||||
);
|
||||
|
||||
if (listType === 'picture-card') {
|
||||
return (
|
||||
<span class={classNames(`${prefixCls.value}-picture-card-wrapper`, attrs.class)}>
|
||||
{renderUploadList(uploadButton)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span class={classNames(`${prefixCls}-picture-card-wrapper`, className)}>
|
||||
{uploadList}
|
||||
<span class={attrs.class}>
|
||||
{uploadButton}
|
||||
{renderUploadList()}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span class={className}>
|
||||
{uploadButton}
|
||||
{uploadList}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -1,284 +0,0 @@
|
||||
import type { CSSProperties } from 'vue';
|
||||
import { defineComponent, inject, nextTick } from 'vue';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import { getOptionProps, initDefaultProps } from '../_util/props-util';
|
||||
import {
|
||||
getTransitionProps,
|
||||
Transition,
|
||||
getTransitionGroupProps,
|
||||
TransitionGroup,
|
||||
} from '../_util/transition';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import { previewImage, isImageUrl } from './utils';
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
import PaperClipOutlined from '@ant-design/icons-vue/PaperClipOutlined';
|
||||
import PictureTwoTone from '@ant-design/icons-vue/PictureTwoTone';
|
||||
import FileTwoTone from '@ant-design/icons-vue/FileOutlined';
|
||||
import DeleteOutlined from '@ant-design/icons-vue/DeleteOutlined';
|
||||
import DownloadOutlined from '@ant-design/icons-vue/DownloadOutlined';
|
||||
import EyeOutlined from '@ant-design/icons-vue/EyeOutlined';
|
||||
import Tooltip from '../tooltip';
|
||||
import Progress from '../progress';
|
||||
import classNames from '../_util/classNames';
|
||||
import { uploadListProps } from './interface';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AUploadList',
|
||||
mixins: [BaseMixin],
|
||||
props: initDefaultProps(uploadListProps, {
|
||||
listType: 'text', // or picture
|
||||
progressAttr: {
|
||||
strokeWidth: 2,
|
||||
showInfo: false,
|
||||
},
|
||||
showRemoveIcon: true,
|
||||
showDownloadIcon: false,
|
||||
showPreviewIcon: true,
|
||||
previewFile: previewImage,
|
||||
}),
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', defaultConfigProvider),
|
||||
};
|
||||
},
|
||||
updated() {
|
||||
nextTick(() => {
|
||||
const { listType, items, previewFile } = this.$props;
|
||||
if (listType !== 'picture' && listType !== 'picture-card') {
|
||||
return;
|
||||
}
|
||||
(items || []).forEach(file => {
|
||||
if (
|
||||
typeof document === 'undefined' ||
|
||||
typeof window === 'undefined' ||
|
||||
!window.FileReader ||
|
||||
!window.File ||
|
||||
!(file.originFileObj instanceof File || file.originFileObj instanceof Blob) ||
|
||||
file.thumbUrl !== undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
/*eslint-disable */
|
||||
file.thumbUrl = '';
|
||||
if (previewFile) {
|
||||
previewFile(file.originFileObj).then(previewDataUrl => {
|
||||
// Need append '' to avoid dead loop
|
||||
file.thumbUrl = previewDataUrl || '';
|
||||
(this as any).$forceUpdate();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
handlePreview(file, e) {
|
||||
const { onPreview } = this.$props;
|
||||
if (!onPreview) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
return this.$emit('preview', file);
|
||||
},
|
||||
handleDownload(file) {
|
||||
const { onDownload } = this.$props;
|
||||
if (typeof onDownload === 'function') {
|
||||
this.$emit('download', file);
|
||||
} else if (file.url) {
|
||||
window.open(file.url);
|
||||
}
|
||||
},
|
||||
|
||||
handleClose(file) {
|
||||
this.$emit('remove', file);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
items = [],
|
||||
listType,
|
||||
showPreviewIcon,
|
||||
showRemoveIcon,
|
||||
showDownloadIcon,
|
||||
locale,
|
||||
progressAttr,
|
||||
} = getOptionProps(this);
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('upload', customizePrefixCls);
|
||||
|
||||
const list = items.map(file => {
|
||||
let progress;
|
||||
let icon = file.status === 'uploading' ? <LoadingOutlined /> : <PaperClipOutlined />;
|
||||
|
||||
if (listType === 'picture' || listType === 'picture-card') {
|
||||
if (listType === 'picture-card' && file.status === 'uploading') {
|
||||
icon = <div class={`${prefixCls}-list-item-uploading-text`}>{locale.uploading}</div>;
|
||||
} else if (!file.thumbUrl && !file.url) {
|
||||
icon = <PictureTwoTone class={`${prefixCls}-list-item-thumbnail`} />;
|
||||
} else {
|
||||
const thumbnail = isImageUrl(file) ? (
|
||||
<img
|
||||
src={file.thumbUrl || file.url}
|
||||
alt={file.name}
|
||||
class={`${prefixCls}-list-item-image`}
|
||||
/>
|
||||
) : (
|
||||
<FileTwoTone class={`${prefixCls}-list-item-icon`} />
|
||||
);
|
||||
icon = (
|
||||
<a
|
||||
class={`${prefixCls}-list-item-thumbnail`}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
href={file.url || file.thumbUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{thumbnail}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (file.status === 'uploading') {
|
||||
const progressProps = {
|
||||
...progressAttr,
|
||||
type: 'line',
|
||||
percent: file.percent,
|
||||
};
|
||||
// show loading icon if upload progress listener is disabled
|
||||
const loadingProgress = 'percent' in file ? <Progress {...progressProps} /> : null;
|
||||
|
||||
progress = (
|
||||
<div class={`${prefixCls}-list-item-progress`} key="progress">
|
||||
{loadingProgress}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const infoUploadingClass = classNames({
|
||||
[`${prefixCls}-list-item`]: true,
|
||||
[`${prefixCls}-list-item-${file.status}`]: true,
|
||||
[`${prefixCls}-list-item-list-type-${listType}`]: true,
|
||||
});
|
||||
const linkProps =
|
||||
typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps;
|
||||
|
||||
const removeIcon = showRemoveIcon ? (
|
||||
<DeleteOutlined title={locale.removeFile} onClick={() => this.handleClose(file)} />
|
||||
) : null;
|
||||
const downloadIcon =
|
||||
showDownloadIcon && file.status === 'done' ? (
|
||||
<DownloadOutlined title={locale.downloadFile} onClick={() => this.handleDownload(file)} />
|
||||
) : null;
|
||||
const downloadOrDelete = listType !== 'picture-card' && (
|
||||
<span
|
||||
key="download-delete"
|
||||
class={`${prefixCls}-list-item-card-actions ${listType === 'picture' ? 'picture' : ''}`}
|
||||
>
|
||||
{downloadIcon && <a title={locale.downloadFile}>{downloadIcon}</a>}
|
||||
{removeIcon && <a title={locale.removeFile}>{removeIcon}</a>}
|
||||
</span>
|
||||
);
|
||||
const listItemNameClass = classNames({
|
||||
[`${prefixCls}-list-item-name`]: true,
|
||||
[`${prefixCls}-list-item-name-icon-count-${
|
||||
[downloadIcon, removeIcon].filter(x => x).length
|
||||
}`]: true,
|
||||
});
|
||||
|
||||
const preview = file.url
|
||||
? [
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class={listItemNameClass}
|
||||
title={file.name}
|
||||
{...linkProps}
|
||||
href={file.url}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
>
|
||||
{file.name}
|
||||
</a>,
|
||||
downloadOrDelete,
|
||||
]
|
||||
: [
|
||||
<span
|
||||
key="view"
|
||||
class={`${prefixCls}-list-item-name`}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
title={file.name}
|
||||
>
|
||||
{file.name}
|
||||
</span>,
|
||||
downloadOrDelete,
|
||||
];
|
||||
const style: CSSProperties | undefined =
|
||||
file.url || file.thumbUrl
|
||||
? undefined
|
||||
: {
|
||||
pointerEvents: 'none',
|
||||
opacity: 0.5,
|
||||
};
|
||||
const previewIcon = showPreviewIcon ? (
|
||||
<a
|
||||
href={file.url || file.thumbUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={style}
|
||||
onClick={e => this.handlePreview(file, e)}
|
||||
title={locale.previewFile}
|
||||
>
|
||||
<EyeOutlined />
|
||||
</a>
|
||||
) : null;
|
||||
const actions = listType === 'picture-card' && file.status !== 'uploading' && (
|
||||
<span class={`${prefixCls}-list-item-actions`}>
|
||||
{previewIcon}
|
||||
{file.status === 'done' && downloadIcon}
|
||||
{removeIcon}
|
||||
</span>
|
||||
);
|
||||
let message;
|
||||
if (file.response && typeof file.response === 'string') {
|
||||
message = file.response;
|
||||
} else {
|
||||
message = (file.error && file.error.statusText) || locale.uploadError;
|
||||
}
|
||||
const iconAndPreview = (
|
||||
<span>
|
||||
{icon}
|
||||
{preview}
|
||||
</span>
|
||||
);
|
||||
const transitionProps = getTransitionProps('fade');
|
||||
const dom = (
|
||||
<div class={infoUploadingClass} key={file.uid}>
|
||||
<div class={`${prefixCls}-list-item-info`}>{iconAndPreview}</div>
|
||||
{actions}
|
||||
<Transition {...transitionProps}>{progress}</Transition>
|
||||
</div>
|
||||
);
|
||||
const listContainerNameClass = classNames({
|
||||
[`${prefixCls}-list-picture-card-container`]: listType === 'picture-card',
|
||||
});
|
||||
return (
|
||||
<div key={file.uid} class={listContainerNameClass}>
|
||||
{file.status === 'error' ? <Tooltip title={message}>{dom}</Tooltip> : <span>{dom}</span>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
const listClassNames = classNames({
|
||||
[`${prefixCls}-list`]: true,
|
||||
[`${prefixCls}-list-${listType}`]: true,
|
||||
});
|
||||
const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate';
|
||||
const transitionGroupProps = {
|
||||
...getTransitionGroupProps(`${prefixCls}-${animationDirection}`),
|
||||
class: listClassNames,
|
||||
};
|
||||
return (
|
||||
<TransitionGroup {...transitionGroupProps} tag="div">
|
||||
{list}
|
||||
</TransitionGroup>
|
||||
);
|
||||
},
|
||||
});
|
286
components/upload/UploadList/ListItem.tsx
Normal file
286
components/upload/UploadList/ListItem.tsx
Normal file
@ -0,0 +1,286 @@
|
||||
import { computed, defineComponent, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import type { ExtractPropTypes, PropType, CSSProperties } from 'vue';
|
||||
import EyeOutlined from '@ant-design/icons-vue/EyeOutlined';
|
||||
import DeleteOutlined from '@ant-design/icons-vue/DeleteOutlined';
|
||||
import DownloadOutlined from '@ant-design/icons-vue/DownloadOutlined';
|
||||
import Tooltip from '../../tooltip';
|
||||
import Progress from '../../progress';
|
||||
|
||||
import type {
|
||||
ItemRender,
|
||||
UploadFile,
|
||||
UploadListProgressProps,
|
||||
UploadListType,
|
||||
UploadLocale,
|
||||
} from '../interface';
|
||||
import type { VueNode } from '../../_util/type';
|
||||
import useConfigInject from '../../_util/hooks/useConfigInject';
|
||||
import Transition, { getTransitionProps } from '../../_util/transition';
|
||||
export const listItemProps = () => {
|
||||
return {
|
||||
prefixCls: String,
|
||||
locale: { type: Object as PropType<UploadLocale>, default: undefined as UploadLocale },
|
||||
file: Object as PropType<UploadFile>,
|
||||
items: Array as PropType<UploadFile[]>,
|
||||
listType: String as PropType<UploadListType>,
|
||||
isImgUrl: Function as PropType<(file: UploadFile) => boolean>,
|
||||
|
||||
showRemoveIcon: { type: Boolean, default: undefined },
|
||||
showDownloadIcon: { type: Boolean, default: undefined },
|
||||
showPreviewIcon: { type: Boolean, default: undefined },
|
||||
removeIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
downloadIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
previewIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
|
||||
iconRender: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
actionIconRender: Function as PropType<
|
||||
(opt: {
|
||||
customIcon: VueNode;
|
||||
callback: () => void;
|
||||
prefixCls: string;
|
||||
title?: string | undefined;
|
||||
}) => VueNode
|
||||
>,
|
||||
itemRender: Function as PropType<ItemRender>,
|
||||
onPreview: Function as PropType<(file: UploadFile, e: Event) => void>,
|
||||
onClose: Function as PropType<(file: UploadFile) => void>,
|
||||
onDownload: Function as PropType<(file: UploadFile) => void>,
|
||||
progress: Object as PropType<UploadListProgressProps>,
|
||||
};
|
||||
};
|
||||
|
||||
export type ListItemProps = Partial<ExtractPropTypes<ReturnType<typeof listItemProps>>>;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ListItem',
|
||||
inheritAttrs: false,
|
||||
props: listItemProps(),
|
||||
setup(props, { slots, attrs }) {
|
||||
const showProgress = ref(false);
|
||||
const progressRafRef = ref();
|
||||
onMounted(() => {
|
||||
progressRafRef.value = setTimeout(() => {
|
||||
showProgress.value = true;
|
||||
}, 300);
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
clearTimeout(progressRafRef.value);
|
||||
});
|
||||
const { rootPrefixCls } = useConfigInject('upload', props);
|
||||
const transitionProps = computed(() => getTransitionProps(`${rootPrefixCls.value}-fade`));
|
||||
return () => {
|
||||
const {
|
||||
prefixCls,
|
||||
locale,
|
||||
listType,
|
||||
file,
|
||||
items,
|
||||
progress: progressProps,
|
||||
iconRender = slots.iconRender,
|
||||
actionIconRender = slots.actionIconRender,
|
||||
itemRender = slots.itemRender,
|
||||
isImgUrl,
|
||||
showPreviewIcon,
|
||||
showRemoveIcon,
|
||||
showDownloadIcon,
|
||||
previewIcon: customPreviewIcon = slots.previewIcon,
|
||||
removeIcon: customRemoveIcon = slots.removeIcon,
|
||||
downloadIcon: customDownloadIcon = slots.downloadIcon,
|
||||
onPreview,
|
||||
onDownload,
|
||||
onClose,
|
||||
} = props;
|
||||
const { class: className, style } = attrs;
|
||||
// This is used for legacy span make scrollHeight the wrong value.
|
||||
// We will force these to be `display: block` with non `picture-card`
|
||||
const spanClassName = `${prefixCls}-span`;
|
||||
|
||||
const iconNode = iconRender({ file });
|
||||
let icon = <div class={`${prefixCls}-text-icon`}>{iconNode}</div>;
|
||||
if (listType === 'picture' || listType === 'picture-card') {
|
||||
if (file.status === 'uploading' || (!file.thumbUrl && !file.url)) {
|
||||
const uploadingClassName = {
|
||||
[`${prefixCls}-list-item-thumbnail`]: true,
|
||||
[`${prefixCls}-list-item-file`]: file.status !== 'uploading',
|
||||
};
|
||||
icon = <div class={uploadingClassName}>{iconNode}</div>;
|
||||
} else {
|
||||
const thumbnail = isImgUrl?.(file) ? (
|
||||
<img
|
||||
src={file.thumbUrl || file.url}
|
||||
alt={file.name}
|
||||
class={`${prefixCls}-list-item-image`}
|
||||
/>
|
||||
) : (
|
||||
iconNode
|
||||
);
|
||||
const aClassName = {
|
||||
[`${prefixCls}-list-item-thumbnail`]: true,
|
||||
[`${prefixCls}-list-item-file`]: isImgUrl && !isImgUrl(file),
|
||||
};
|
||||
icon = (
|
||||
<a
|
||||
class={aClassName}
|
||||
onClick={e => onPreview(file, e)}
|
||||
href={file.url || file.thumbUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{thumbnail}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const infoUploadingClass = {
|
||||
[`${prefixCls}-list-item`]: true,
|
||||
[`${prefixCls}-list-item-${file.status}`]: true,
|
||||
[`${prefixCls}-list-item-list-type-${listType}`]: true,
|
||||
};
|
||||
const linkProps =
|
||||
typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps;
|
||||
|
||||
const removeIcon = showRemoveIcon
|
||||
? actionIconRender({
|
||||
customIcon: customRemoveIcon ? customRemoveIcon({ file }) : <DeleteOutlined />,
|
||||
callback: () => onClose(file),
|
||||
prefixCls,
|
||||
title: locale.removeFile,
|
||||
})
|
||||
: null;
|
||||
const downloadIcon =
|
||||
showDownloadIcon && file.status === 'done'
|
||||
? actionIconRender({
|
||||
customIcon: customDownloadIcon ? customDownloadIcon({ file }) : <DownloadOutlined />,
|
||||
callback: () => onDownload(file),
|
||||
prefixCls,
|
||||
title: locale.downloadFile,
|
||||
})
|
||||
: null;
|
||||
const downloadOrDelete = listType !== 'picture-card' && (
|
||||
<span
|
||||
key="download-delete"
|
||||
class={[
|
||||
`${prefixCls}-list-item-card-actions`,
|
||||
{
|
||||
picture: listType === 'picture',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{downloadIcon}
|
||||
{removeIcon}
|
||||
</span>
|
||||
);
|
||||
const listItemNameClass = `${prefixCls}-list-item-name`;
|
||||
const preview = file.url
|
||||
? [
|
||||
<a
|
||||
key="view"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class={listItemNameClass}
|
||||
title={file.name}
|
||||
{...linkProps}
|
||||
href={file.url}
|
||||
onClick={e => onPreview(file, e)}
|
||||
>
|
||||
{file.name}
|
||||
</a>,
|
||||
downloadOrDelete,
|
||||
]
|
||||
: [
|
||||
<span
|
||||
key="view"
|
||||
class={listItemNameClass}
|
||||
onClick={e => onPreview(file, e)}
|
||||
title={file.name}
|
||||
>
|
||||
{file.name}
|
||||
</span>,
|
||||
downloadOrDelete,
|
||||
];
|
||||
const previewStyle: CSSProperties = {
|
||||
pointerEvents: 'none',
|
||||
opacity: 0.5,
|
||||
};
|
||||
const previewIcon = showPreviewIcon ? (
|
||||
<a
|
||||
href={file.url || file.thumbUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={file.url || file.thumbUrl ? undefined : previewStyle}
|
||||
onClick={e => onPreview(file, e)}
|
||||
title={locale.previewFile}
|
||||
>
|
||||
{customPreviewIcon ? customPreviewIcon({ file }) : <EyeOutlined />}
|
||||
</a>
|
||||
) : null;
|
||||
|
||||
const actions = listType === 'picture-card' && file.status !== 'uploading' && (
|
||||
<span class={`${prefixCls}-list-item-actions`}>
|
||||
{previewIcon}
|
||||
{file.status === 'done' && downloadIcon}
|
||||
{removeIcon}
|
||||
</span>
|
||||
);
|
||||
|
||||
let message;
|
||||
if (file.response && typeof file.response === 'string') {
|
||||
message = file.response;
|
||||
} else {
|
||||
message = file.error?.statusText || file.error?.message || locale.uploadError;
|
||||
}
|
||||
const iconAndPreview = (
|
||||
<span class={spanClassName}>
|
||||
{icon}
|
||||
{preview}
|
||||
</span>
|
||||
);
|
||||
|
||||
const dom = (
|
||||
<div class={infoUploadingClass}>
|
||||
<div class={`${prefixCls}-list-item-info`}>{iconAndPreview}</div>
|
||||
{actions}
|
||||
{showProgress.value && (
|
||||
<Transition {...transitionProps.value}>
|
||||
<div v-show={file.status === 'uploading'} class={`${prefixCls}-list-item-progress`}>
|
||||
{'percent' in file ? (
|
||||
<Progress {...progressProps} type="line" percent={file.percent} />
|
||||
) : null}
|
||||
</div>
|
||||
</Transition>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
const listContainerNameClass = {
|
||||
[`${prefixCls}-list-${listType}-container`]: true,
|
||||
[`${className}`]: !!className,
|
||||
};
|
||||
const item =
|
||||
file.status === 'error' ? (
|
||||
<Tooltip title={message} getPopupContainer={node => node.parentNode as HTMLElement}>
|
||||
{dom}
|
||||
</Tooltip>
|
||||
) : (
|
||||
dom
|
||||
);
|
||||
|
||||
return (
|
||||
<div class={listContainerNameClass} style={style} ref={ref}>
|
||||
{itemRender
|
||||
? itemRender({
|
||||
originNode: item,
|
||||
file,
|
||||
fileList: items,
|
||||
actions: {
|
||||
download: onDownload.bind(null, file),
|
||||
preview: onPreview.bind(null, file),
|
||||
remove: onClose.bind(null, file),
|
||||
},
|
||||
})
|
||||
: item}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
211
components/upload/UploadList/index.tsx
Normal file
211
components/upload/UploadList/index.tsx
Normal file
@ -0,0 +1,211 @@
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
import PaperClipOutlined from '@ant-design/icons-vue/PaperClipOutlined';
|
||||
import PictureTwoTone from '@ant-design/icons-vue/PictureTwoTone';
|
||||
import FileTwoTone from '@ant-design/icons-vue/FileTwoTone';
|
||||
import type { UploadListType, InternalUploadFile, UploadFile } from '../interface';
|
||||
import { uploadListProps } from '../interface';
|
||||
import { previewImage, isImageUrl } from '../utils';
|
||||
import type { ButtonProps } from '../../button';
|
||||
import Button from '../../button';
|
||||
import ListItem from './ListItem';
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { computed, defineComponent, getCurrentInstance, onMounted, ref, watchEffect } from 'vue';
|
||||
import { initDefaultProps, isValidElement } from '../../_util/props-util';
|
||||
import type { VueNode } from '../../_util/type';
|
||||
import useConfigInject from '../../_util/hooks/useConfigInject';
|
||||
import { getTransitionGroupProps, TransitionGroup } from '../../_util/transition';
|
||||
import listAnimation from './listAnimation';
|
||||
|
||||
const HackSlot = (_, { slots }) => {
|
||||
return slots.default?.()[0];
|
||||
};
|
||||
export default defineComponent({
|
||||
name: 'AUploadList',
|
||||
props: initDefaultProps(uploadListProps(), {
|
||||
listType: 'text' as UploadListType, // or picture
|
||||
progress: {
|
||||
strokeWidth: 2,
|
||||
showInfo: false,
|
||||
},
|
||||
showRemoveIcon: true,
|
||||
showDownloadIcon: false,
|
||||
showPreviewIcon: true,
|
||||
previewFile: previewImage,
|
||||
isImageUrl,
|
||||
items: [],
|
||||
}),
|
||||
setup(props, { slots, expose }) {
|
||||
const motionAppear = ref(false);
|
||||
const instance = getCurrentInstance();
|
||||
onMounted(() => {
|
||||
motionAppear.value == true;
|
||||
});
|
||||
watchEffect(() => {
|
||||
if (props.listType !== 'picture' && props.listType !== 'picture-card') {
|
||||
return;
|
||||
}
|
||||
(props.items || []).forEach((file: InternalUploadFile) => {
|
||||
if (
|
||||
typeof document === 'undefined' ||
|
||||
typeof window === 'undefined' ||
|
||||
!(window as any).FileReader ||
|
||||
!(window as any).File ||
|
||||
!(file.originFileObj instanceof File || (file.originFileObj as Blob) instanceof Blob) ||
|
||||
file.thumbUrl !== undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
file.thumbUrl = '';
|
||||
if (props.previewFile) {
|
||||
props.previewFile(file.originFileObj as File).then((previewDataUrl: string) => {
|
||||
// Need append '' to avoid dead loop
|
||||
file.thumbUrl = previewDataUrl || '';
|
||||
instance.update();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ============================= Events =============================
|
||||
const onInternalPreview = (file: UploadFile, e?: Event) => {
|
||||
if (!props.onPreview) {
|
||||
return;
|
||||
}
|
||||
e?.preventDefault();
|
||||
return props.onPreview(file);
|
||||
};
|
||||
|
||||
const onInternalDownload = (file: UploadFile) => {
|
||||
if (typeof props.onDownload === 'function') {
|
||||
props.onDownload(file);
|
||||
} else if (file.url) {
|
||||
window.open(file.url);
|
||||
}
|
||||
};
|
||||
|
||||
const onInternalClose = (file: UploadFile) => {
|
||||
props.onRemove?.(file);
|
||||
};
|
||||
|
||||
const internalIconRender = ({ file }: { file: UploadFile }) => {
|
||||
const iconRender = props.iconRender || slots.iconRender;
|
||||
if (iconRender) {
|
||||
return iconRender({ file, listType: props.listType });
|
||||
}
|
||||
const isLoading = file.status === 'uploading';
|
||||
const fileIcon =
|
||||
props.isImageUrl && props.isImageUrl(file) ? <PictureTwoTone /> : <FileTwoTone />;
|
||||
let icon: VueNode = isLoading ? <LoadingOutlined /> : <PaperClipOutlined />;
|
||||
if (props.listType === 'picture') {
|
||||
icon = isLoading ? <LoadingOutlined /> : fileIcon;
|
||||
} else if (props.listType === 'picture-card') {
|
||||
icon = isLoading ? props.locale.uploading : fileIcon;
|
||||
}
|
||||
return icon;
|
||||
};
|
||||
|
||||
const actionIconRender = (opt: {
|
||||
customIcon: VueNode;
|
||||
callback: () => void;
|
||||
prefixCls: string;
|
||||
title?: string;
|
||||
}) => {
|
||||
const { customIcon, callback, prefixCls, title } = opt;
|
||||
const btnProps: ButtonProps & HTMLAttributes = {
|
||||
type: 'text',
|
||||
size: 'small',
|
||||
title,
|
||||
onClick: () => {
|
||||
callback();
|
||||
},
|
||||
class: `${prefixCls}-list-item-card-actions-btn`,
|
||||
};
|
||||
if (isValidElement(customIcon)) {
|
||||
return <Button {...btnProps} v-slots={{ icon: () => customIcon }} />;
|
||||
}
|
||||
return (
|
||||
<Button {...btnProps}>
|
||||
<span>{customIcon}</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
expose({
|
||||
handlePreview: onInternalPreview,
|
||||
handleDownload: onInternalDownload,
|
||||
});
|
||||
|
||||
const { prefixCls, direction } = useConfigInject('upload', props);
|
||||
|
||||
const listClassNames = computed(() => ({
|
||||
[`${prefixCls.value}-list`]: true,
|
||||
[`${prefixCls.value}-list-${props.listType}`]: true,
|
||||
[`${prefixCls.value}-list-rtl`]: direction.value === 'rtl',
|
||||
}));
|
||||
const transitionGroupProps = computed(() => ({
|
||||
...listAnimation(
|
||||
`${prefixCls.value}-${props.listType === 'picture-card' ? 'animate-inline' : 'animate'}`,
|
||||
),
|
||||
...getTransitionGroupProps(
|
||||
`${prefixCls.value}-${props.listType === 'picture-card' ? 'animate-inline' : 'animate'}`,
|
||||
),
|
||||
class: listClassNames.value,
|
||||
appear: motionAppear.value,
|
||||
}));
|
||||
return () => {
|
||||
const {
|
||||
listType,
|
||||
locale,
|
||||
isImageUrl: isImgUrl,
|
||||
items = [],
|
||||
showPreviewIcon,
|
||||
showRemoveIcon,
|
||||
showDownloadIcon,
|
||||
removeIcon,
|
||||
previewIcon,
|
||||
downloadIcon,
|
||||
progress,
|
||||
appendAction = slots.appendAction,
|
||||
itemRender,
|
||||
} = props;
|
||||
const appendActionDom = appendAction?.()[0];
|
||||
return (
|
||||
<TransitionGroup {...transitionGroupProps.value} tag="div">
|
||||
{items.map(file => {
|
||||
const { uid: key } = file;
|
||||
return (
|
||||
<ListItem
|
||||
key={key}
|
||||
locale={locale}
|
||||
prefixCls={prefixCls.value}
|
||||
file={file}
|
||||
items={items}
|
||||
progress={progress}
|
||||
listType={listType}
|
||||
isImgUrl={isImgUrl}
|
||||
showPreviewIcon={showPreviewIcon}
|
||||
showRemoveIcon={showRemoveIcon}
|
||||
showDownloadIcon={showDownloadIcon}
|
||||
onPreview={onInternalPreview}
|
||||
onDownload={onInternalDownload}
|
||||
onClose={onInternalClose}
|
||||
removeIcon={removeIcon}
|
||||
previewIcon={previewIcon}
|
||||
downloadIcon={downloadIcon}
|
||||
itemRender={itemRender}
|
||||
v-slots={{
|
||||
...slots,
|
||||
iconRender: internalIconRender,
|
||||
actionIconRender,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{isValidElement(appendActionDom) ? (
|
||||
<HackSlot key="__ant_upload_appendAction">{appendActionDom}</HackSlot>
|
||||
) : null}
|
||||
</TransitionGroup>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
44
components/upload/UploadList/listAnimation.ts
Normal file
44
components/upload/UploadList/listAnimation.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { addClass, removeClass } from '../../vc-util/Dom/class';
|
||||
import { nextTick } from 'vue';
|
||||
import type { CSSMotionProps } from '../../_util/transition';
|
||||
|
||||
const listAnimation = (name): CSSMotionProps => {
|
||||
return {
|
||||
name,
|
||||
appear: true,
|
||||
css: true,
|
||||
onBeforeEnter: (node: HTMLDivElement) => {
|
||||
addClass(node, name);
|
||||
node.style.height = '0px';
|
||||
node.style.opacity = '0';
|
||||
},
|
||||
onEnter: (node: HTMLDivElement) => {
|
||||
nextTick(() => {
|
||||
node.style.height = `${node.scrollHeight}px`;
|
||||
node.style.opacity = '1';
|
||||
});
|
||||
},
|
||||
onAfterEnter: (node: HTMLDivElement) => {
|
||||
if (node) removeClass(node, name);
|
||||
node.style.height = undefined;
|
||||
node.style.opacity = undefined;
|
||||
},
|
||||
onBeforeLeave: (node: HTMLDivElement) => {
|
||||
addClass(node, name);
|
||||
node.style.height = `${node.offsetHeight}px`;
|
||||
node.style.opacity = undefined;
|
||||
},
|
||||
onLeave: (node: HTMLDivElement) => {
|
||||
setTimeout(() => {
|
||||
node.style.height = '0px';
|
||||
node.style.opacity = '0';
|
||||
});
|
||||
},
|
||||
onAfterLeave: (node: HTMLDivElement) => {
|
||||
if (node) removeClass(node, name);
|
||||
node.style.height = undefined;
|
||||
node.style.opacity = undefined;
|
||||
},
|
||||
};
|
||||
};
|
||||
export default listAnimation;
|
@ -1,126 +1,305 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/upload/demo/avatar.vue correctly 1`] = `
|
||||
<span class="ant-upload-picture-card-wrapper avatar-uploader"><!----><div class="ant-upload ant-upload-select ant-upload-select-picture-card"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><div><span role="img" aria-label="plus" class="anticon anticon-plus"><svg focusable="false" class="" data-icon="plus" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><defs><style></style></defs><path d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"></path><path d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"></path></svg></span>
|
||||
<span class="ant-upload-picture-card-wrapper avatar-uploader"><div class="ant-upload ant-upload-select ant-upload-select-picture-card"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><div><span role="img" aria-label="plus" class="anticon anticon-plus"><svg focusable="false" class="" data-icon="plus" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><defs><style></style></defs><path d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"></path><path d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"></path></svg></span>
|
||||
<div class="ant-upload-text">Upload</div>
|
||||
</div></span></div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/basic.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept="" multiple=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text"></div></span>
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/custom-render.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-space ant-space-horizontal ant-space-align-center">
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><span style="">xxx.png</span></div>
|
||||
<!---->
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><a href="javascript:;">download</a></div>
|
||||
<!---->
|
||||
<div class="ant-space-item"><a href="javascript:;">delete</a></div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-space ant-space-horizontal ant-space-align-center">
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><span style="">yyy.png</span></div>
|
||||
<!---->
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><a href="javascript:;">download</a></div>
|
||||
<!---->
|
||||
<div class="ant-space-item"><a href="javascript:;">delete</a></div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-space ant-space-horizontal ant-space-align-center">
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><span style="color: red;">zzz.png</span></div>
|
||||
<!---->
|
||||
<div class="ant-space-item" style="margin-right: 8px;"><a href="javascript:;">download</a></div>
|
||||
<!---->
|
||||
<div class="ant-space-item"><a href="javascript:;">delete</a></div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/customize-progress-bar.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Click to Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/defaultFileList.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"><div class="ant-upload-list-item-info"><span><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="xxx.png" href="http://www.baidu.com/xxx.png">xxx.png</a><span class="ant-upload-list-item-card-actions "><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"><div class="ant-upload-list-item-info"><span><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="yyy.png" href="http://www.baidu.com/yyy.png">yyy.png</a><span class="ant-upload-list-item-card-actions "><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class="">
|
||||
<!---->
|
||||
<div class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="zzz.png" href="http://www.baidu.com/zzz.png">zzz.png</a><span class="ant-upload-list-item-card-actions "><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="xxx.png" href="http://www.baidu.com/xxx.png">xxx.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="yyy.png" href="http://www.baidu.com/yyy.png">yyy.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<!---->
|
||||
<div class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="zzz.png" href="http://www.baidu.com/zzz.png">zzz.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/directory.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept="" directory="directory" webkitdirectory="webkitdirectory"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload Directory</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text"></div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/drag.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-drag"><span role="button" tabindex="0" class="ant-upload ant-upload-btn"><input type="file" style="display: none;" accept="" multiple=""><div class="ant-upload-drag-container"><p class="ant-upload-drag-icon"><span role="img" aria-label="inbox" class="anticon anticon-inbox"><svg focusable="false" class="" data-icon="inbox" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"></path></svg></span></p>
|
||||
<p class="ant-upload-text">Click or drag file to this area to upload</p>
|
||||
<p class="ant-upload-hint"> Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files </p>
|
||||
</div></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text"></div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/fileList.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept="" multiple=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" directory="directory" webkitdirectory="webkitdirectory" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload Directory</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text"><div class="ant-upload-list-item-info"><span><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="xxx.png" href="http://www.baidu.com/xxx.png">xxx.png</a><span class="ant-upload-list-item-card-actions "><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/picture-card.vue correctly 1`] = `
|
||||
<div class="clearfix"><span class="ant-upload-picture-card-wrapper"><div class="ant-upload-list ant-upload-list-picture-card"><div class="ant-upload-list-picture-card-container"><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></span>
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class="ant-upload-list-picture-card-container"><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></span>
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class="ant-upload-list-picture-card-container"><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></span>
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class="ant-upload-list-picture-card-container"><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></span>
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class="ant-upload-list-picture-card-container">
|
||||
exports[`renders ./components/upload/demo/drag.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-drag"><span tabindex="0" class="ant-upload ant-upload-btn" role="button"><input type="file" style="display: none;" accept="" multiple="" capture="false"><p class="ant-upload-drag-icon"><span role="img" aria-label="inbox" class="anticon anticon-inbox"><svg focusable="false" class="" data-icon="inbox" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M885.2 446.3l-.2-.8-112.2-285.1c-5-16.1-19.9-27.2-36.8-27.2H281.2c-17 0-32.1 11.3-36.9 27.6L139.4 443l-.3.7-.2.8c-1.3 4.9-1.7 9.9-1 14.8-.1 1.6-.2 3.2-.2 4.8V830a60.9 60.9 0 0060.8 60.8h627.2c33.5 0 60.8-27.3 60.9-60.8V464.1c0-1.3 0-2.6-.1-3.7.4-4.9 0-9.6-1.3-14.1zm-295.8-43l-.3 15.7c-.8 44.9-31.8 75.1-77.1 75.1-22.1 0-41.1-7.1-54.8-20.6S436 441.2 435.6 419l-.3-15.7H229.5L309 210h399.2l81.7 193.3H589.4zm-375 76.8h157.3c24.3 57.1 76 90.8 140.4 90.8 33.7 0 65-9.4 90.3-27.2 22.2-15.6 39.5-37.4 50.7-63.6h156.5V814H214.4V480.1z"></path></svg></span></p>
|
||||
<p class="ant-upload-text">Click or drag file to this area to upload</p>
|
||||
<p class="ant-upload-hint"> Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files </p></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<!---->
|
||||
<div class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-picture-card">
|
||||
<div class="ant-upload-list-item-info"><span><span role="img" aria-label="picture" class="anticon anticon-picture ant-upload-list-item-thumbnail"><svg focusable="false" class="" data-icon="picture" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zm-40 632H136v-39.9l138.5-164.3 150.1 178L658.1 489 888 761.6V792zm0-129.8L664.2 396.8c-3.2-3.8-9-3.8-12.2 0L424.6 666.4l-144-170.7c-3.2-3.8-9-3.8-12.2 0L136 652.7V232h752v430.2z" fill="#1890ff"></path><path d="M424.6 765.8l-150.1-178L136 752.1V792h752v-30.4L658.1 489z" fill="#e6f7ff"></path><path d="M136 652.7l132.4-157c3.2-3.8 9-3.8 12.2 0l144 170.7L652 396.8c3.2-3.8 9-3.8 12.2 0L888 662.2V232H136v420.7zM304 280a88 88 0 110 176 88 88 0 010-176z" fill="#e6f7ff"></path><path d="M276 368a28 28 0 1056 0 28 28 0 10-56 0z" fill="#e6f7ff"></path><path d="M304 456a88 88 0 100-176 88 88 0 000 176zm0-116c15.5 0 28 12.5 28 28s-12.5 28-28 28-28-12.5-28-28 12.5-28 28-28z" fill="#1890ff"></path></svg></span><span class="ant-upload-list-item-name" title="image.png">image.png</span>
|
||||
<!----></span>
|
||||
</div><span class="ant-upload-list-item-actions"><a target="_blank" rel="noopener noreferrer" style="pointer-events: none; opacity: 0.5;" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></span>
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/fileList.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" multiple="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="xxx.png" href="http://www.baidu.com/xxx.png">xxx.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/max-count.vue correctly 1`] = `
|
||||
<div class="ant-space ant-space-vertical" style="width: 100%;">
|
||||
<div class="ant-space-item" style="margin-bottom: 24px;"><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload (Max: 1)</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<!---->
|
||||
</div></span>
|
||||
</div>
|
||||
<div class="ant-upload ant-upload-select ant-upload-select-picture-card"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><div><span role="img" aria-label="plus" class="anticon anticon-plus"><svg focusable="false" class="" data-icon="plus" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><defs><style></style></defs><path d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"></path><path d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"></path></svg></span>
|
||||
<div class="ant-upload-text">Upload</div>
|
||||
</div></span></div></span>
|
||||
<!---->
|
||||
<div class="ant-space-item"><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload (Max: 3)</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/picture-card.vue correctly 1`] = `
|
||||
<div class="clearfix"><span class="ant-upload-picture-card-wrapper"><div class="ant-upload-list ant-upload-list-picture-card"><div class="ant-upload-list-picture-card-container"><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card"><div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-card-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-card-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-card-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="image.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div><span class="ant-upload-list-item-actions"><a href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-card-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-uploading ant-upload-list-item-list-type-picture-card">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-list-item-thumbnail">Uploading...</div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">image.png</a><!----></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-card-container">
|
||||
<!---->
|
||||
<div class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-picture-card">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-list-item-thumbnail ant-upload-list-item-file"><span role="img" aria-label="picture" class="anticon anticon-picture"><svg focusable="false" class="" data-icon="picture" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zm-40 632H136v-39.9l138.5-164.3 150.1 178L658.1 489 888 761.6V792zm0-129.8L664.2 396.8c-3.2-3.8-9-3.8-12.2 0L424.6 666.4l-144-170.7c-3.2-3.8-9-3.8-12.2 0L136 652.7V232h752v430.2z" fill="#1890ff"></path><path d="M424.6 765.8l-150.1-178L136 752.1V792h752v-30.4L658.1 489z" fill="#e6f7ff"></path><path d="M136 652.7l132.4-157c3.2-3.8 9-3.8 12.2 0l144 170.7L652 396.8c3.2-3.8 9-3.8 12.2 0L888 662.2V232H136v420.7zM304 280a88 88 0 110 176 88 88 0 010-176z" fill="#e6f7ff"></path><path d="M276 368a28 28 0 1056 0 28 28 0 10-56 0z" fill="#e6f7ff"></path><path d="M304 456a88 88 0 100-176 88 88 0 000 176zm0-116c15.5 0 28 12.5 28 28s-12.5 28-28 28-28-12.5-28-28 12.5-28 28-28z" fill="#1890ff"></path></svg></span></div><span class="ant-upload-list-item-name" title="image.png">image.png</span>
|
||||
<!----></span>
|
||||
</div><span class="ant-upload-list-item-actions"><a target="_blank" rel="noopener noreferrer" style="pointer-events: none; opacity: 0.5;" title="Preview file"><span role="img" aria-label="eye" class="anticon anticon-eye"><svg focusable="false" class="" data-icon="eye" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 000 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z"></path></svg></span></a>
|
||||
<!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload ant-upload-select ant-upload-select-picture-card"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><div><span role="img" aria-label="plus" class="anticon anticon-plus"><svg focusable="false" class="" data-icon="plus" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><defs><style></style></defs><path d="M482 152h60q8 0 8 8v704q0 8-8 8h-60q-8 0-8-8V160q0-8 8-8z"></path><path d="M176 474h672q8 0 8 8v60q0 8-8 8H176q-8 0-8-8v-60q0-8 8-8z"></path></svg></span>
|
||||
<div style="margin-top: 8px;">Upload</div>
|
||||
</div></span></div>
|
||||
</div></span>
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/picture-style.vue correctly 1`] = `
|
||||
<div><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>upload</span></button></span></div>
|
||||
<div><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="xxx.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="xxx.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">xxx.png</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="xxx.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="xxx.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">xxx.png</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="yyy.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="yyy.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">yyy.png</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="yyy.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="yyy.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">yyy.png</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
</div></span><br><br><span class="upload-list-inline"><div class="ant-upload ant-upload-select ant-upload-select-picture"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>upload</span></button></span></div>
|
||||
</div></span><br><br><span class="upload-list-inline"><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="xxx.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="xxx.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">xxx.png</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="xxx.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="xxx.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">xxx.png</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="yyy.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="yyy.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">yyy.png</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" target="_blank" rel="noopener noreferrer"><img src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" alt="yyy.png" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="yyy.png" href="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">yyy.png</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
</div></span></div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/preview-file.vue correctly 1`] = `
|
||||
<div><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture"></div></span></div>
|
||||
<div><span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<!---->
|
||||
</div></span></div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/transform-file.vue correctly 1`] = `
|
||||
<div><span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" style="display: none;" accept=""><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text"></div></span></div>
|
||||
<div><span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<!---->
|
||||
</div></span></div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/upload-custom-action-icon.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="xxx.png" href="http://www.baidu.com/xxx.png">xxx.png</a><span class="ant-upload-list-item-card-actions"><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn" title="Download file" type="button"><!----><span>download</span></button><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span tabindex="-1" role="img" aria-label="star" class="anticon anticon-star"><svg focusable="false" class="" data-icon="star" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3zM664.8 561.6l36.1 210.3L512 672.7 323.1 772l36.1-210.3-152.8-149L417.6 382 512 190.7 606.4 382l211.2 30.7-152.8 148.9z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="yyy.png" href="http://www.baidu.com/yyy.png">yyy.png</a><span class="ant-upload-list-item-card-actions"><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn" title="Download file" type="button"><!----><span>download</span></button><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span tabindex="-1" role="img" aria-label="star" class="anticon anticon-star"><svg focusable="false" class="" data-icon="star" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3zM664.8 561.6l36.1 210.3L512 672.7 323.1 772l36.1-210.3-152.8-149L417.6 382 512 190.7 606.4 382l211.2 30.7-152.8 148.9z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<!---->
|
||||
<div class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="zzz.png" href="http://www.baidu.com/zzz.png">zzz.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span tabindex="-1" role="img" aria-label="star" class="anticon anticon-star"><svg focusable="false" class="" data-icon="star" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3zM664.8 561.6l36.1 210.3L512 672.7 323.1 772l36.1-210.3-152.8-149L417.6 382 512 190.7 606.4 382l211.2 30.7-152.8 148.9z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/upload/demo/upload-png-only.vue correctly 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button class="ant-btn" type="button"><!----><span role="img" aria-label="upload" class="anticon anticon-upload"><svg focusable="false" class="" data-icon="upload" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"></path></svg></span><span>Upload png only</span></button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-text">
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="xxx.png" href="http://www.baidu.com/xxx.png">xxx.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="yyy.png" href="http://www.baidu.com/yyy.png">yyy.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-text-container">
|
||||
<!---->
|
||||
<div class="ant-upload-list-item ant-upload-list-item-error ant-upload-list-item-list-type-text">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><div class="ant-upload-text-icon"><span role="img" aria-label="paper-clip" class="anticon anticon-paper-clip"><svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg></span></div><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="zzz.png" href="http://www.baidu.com/zzz.png">zzz.png</a><span class="ant-upload-list-item-card-actions"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
@ -35,41 +35,71 @@ exports[`Upload List handle error 2`] = `
|
||||
exports[`Upload List should be uploading when upload a file 1`] = `<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" accept="" style="display: none;"><button>upload</button></span></div><span tag="div" class="ant-upload-list ant-upload-list-text"></span></span>`;
|
||||
|
||||
exports[`Upload List should non-image format file preview 1`] = `
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-picture"><!----></div><div class="ant-upload-list ant-upload-list-picture"><div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa.zip" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file ant-upload-list-item-icon"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="not-image" href="https://cdn.xxx.com/aaa.zip">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/aaa" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image" href="https://cdn.xxx.com/aaa">image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa.xx" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file ant-upload-list-item-icon"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="not-image" href="https://cdn.xxx.com/aaa.xx">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa.png/xx.xx" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file ant-upload-list-item-icon"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="not-image" href="https://cdn.xxx.com/aaa.png/xx.xx">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png">image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png" target="_blank" rel="noopener noreferrer"><img src="data:image/png;base64,UEsDBAoAAAAAADYZYkwAAAAAAAAAAAAAAAAdAAk" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png">image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png?query=123" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png?query=123" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png?query=123">image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png#anchor" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png#anchor" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png#anchor">image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png?query=some.query.with.dot" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png?query=some.query.with.dot" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png?query=some.query.with.dot">image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div></span></div>
|
||||
<span><div class="ant-upload ant-upload-select ant-upload-select-picture"><span tabindex="0" class="ant-upload" role="button"><input type="file" style="display: none;" accept="" capture="false"><button>upload</button></span></div>
|
||||
<div class="ant-upload-list ant-upload-list-picture">
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail ant-upload-list-item-file" href="https://cdn.xxx.com/aaa.zip" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M534 352V136H232v752h560V394H576a42 42 0 01-42-42z" fill="#e6f7ff"></path><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM602 137.8L790.2 326H602V137.8zM792 888H232V136h302v216a42 42 0 0042 42h216v494z" fill="#1890ff"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="not-image" href="https://cdn.xxx.com/aaa.zip">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/aaa" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image" href="https://cdn.xxx.com/aaa">image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail ant-upload-list-item-file" href="https://cdn.xxx.com/aaa.xx" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M534 352V136H232v752h560V394H576a42 42 0 01-42-42z" fill="#e6f7ff"></path><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM602 137.8L790.2 326H602V137.8zM792 888H232V136h302v216a42 42 0 0042 42h216v494z" fill="#1890ff"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="not-image" href="https://cdn.xxx.com/aaa.xx">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail ant-upload-list-item-file" href="https://cdn.xxx.com/aaa.png/xx.xx" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M534 352V136H232v752h560V394H576a42 42 0 01-42-42z" fill="#e6f7ff"></path><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM602 137.8L790.2 326H602V137.8zM792 888H232V136h302v216a42 42 0 0042 42h216v494z" fill="#1890ff"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="not-image" href="https://cdn.xxx.com/aaa.png/xx.xx">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png">image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png" target="_blank" rel="noopener noreferrer"><img src="data:image/png;base64,UEsDBAoAAAAAADYZYkwAAAAAAAAAAAAAAAAdAAk" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png">image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png?query=123" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png?query=123" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png?query=123">image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png#anchor" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png#anchor" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png#anchor">image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-upload-list-picture-container">
|
||||
<div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture">
|
||||
<div class="ant-upload-list-item-info"><span class="ant-upload-span"><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/xx.xx/aaa.png?query=some.query.with.dot" target="_blank" rel="noopener noreferrer"><img src="https://cdn.xxx.com/xx.xx/aaa.png?query=some.query.with.dot" alt="image" class="ant-upload-list-item-image"></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="image" href="https://cdn.xxx.com/xx.xx/aaa.png?query=some.query.with.dot">image</a><span class="ant-upload-list-item-card-actions picture"><!----><button class="ant-btn ant-btn-text ant-btn-sm ant-upload-list-item-card-actions-btn ant-btn-icon-only" title="Remove file" type="button"><span role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></button></span></span></div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div></span>
|
||||
`;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { mount } from '@vue/test-utils';
|
||||
import Upload from '..';
|
||||
import { T, fileToObject, genPercentAdd, getFileItem, removeFileItem } from '../utils';
|
||||
import { getFileItem, removeFileItem } from '../utils';
|
||||
import PropsTypes from '../../_util/vue-types';
|
||||
import { uploadListProps } from '../interface';
|
||||
import { setup, teardown } from './mock';
|
||||
@ -199,36 +199,6 @@ describe('Upload', () => {
|
||||
});
|
||||
|
||||
describe('util', () => {
|
||||
// https://github.com/react-component/upload/issues/36
|
||||
it('should T() return true', () => {
|
||||
const res = T();
|
||||
expect(res).toBe(true);
|
||||
});
|
||||
it('should be able to copy file instance', () => {
|
||||
const file = new File([], 'aaa.zip');
|
||||
const copiedFile = fileToObject(file);
|
||||
['uid', 'lastModified', 'lastModifiedDate', 'name', 'size', 'type'].forEach(key => {
|
||||
expect(key in copiedFile).toBe(true);
|
||||
});
|
||||
});
|
||||
it('should be able to progress from 0.1 ', () => {
|
||||
// 0.1 -> 0.98
|
||||
const getPercent = genPercentAdd();
|
||||
let curPercent = 0;
|
||||
curPercent = getPercent(curPercent);
|
||||
expect(curPercent).toBe(0.1);
|
||||
});
|
||||
|
||||
it('should be able to progress to 0.98 ', () => {
|
||||
// 0.1 -> 0.98
|
||||
const getPercent = genPercentAdd();
|
||||
let curPercent = 0;
|
||||
for (let i = 0; i < 500; i += 1) {
|
||||
curPercent = getPercent(curPercent);
|
||||
}
|
||||
expect(parseFloat(curPercent.toFixed(2))).toBe(0.98);
|
||||
});
|
||||
|
||||
it('should be able to get fileItem', () => {
|
||||
const file = { uid: '-1', name: 'item.jpg' };
|
||||
const fileList = [
|
||||
|
@ -300,7 +300,7 @@ describe('Upload List', () => {
|
||||
defaultFileList: fileList,
|
||||
listType: 'picture-card',
|
||||
action: '',
|
||||
remove: handleRemove,
|
||||
onRemove: handleRemove,
|
||||
onChange: handleChange,
|
||||
},
|
||||
|
||||
|
@ -10,7 +10,7 @@ title:
|
||||
|
||||
点击上传用户头像,并使用 `beforeUpload` 限制用户上传的图片格式和大小。
|
||||
|
||||
> `beforeUpload` 的返回值可以是一个 Promise 以支持异步处理,如服务端校验等:[示例](http://react-component.github.io/upload/examples/beforeUpload.html)。
|
||||
> `beforeUpload` 的返回值可以是一个 Promise 以支持异步处理,如服务端校验等:可参考react版本[示例](http://react-component.github.io/upload/examples/beforeUpload.html)。
|
||||
|
||||
## en-US
|
||||
|
||||
|
@ -19,7 +19,6 @@ Classic mode. File selection dialog pops up when upload button is clicked.
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
:multiple="true"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:headers="headers"
|
||||
@change="handleChange"
|
||||
|
93
components/upload/demo/custom-render.vue
Normal file
93
components/upload/demo/custom-render.vue
Normal file
@ -0,0 +1,93 @@
|
||||
<docs>
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 自定义上传列表
|
||||
en-US: Custom Render
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `itemRender` 插槽进行完全自定义列表
|
||||
|
||||
## en-US
|
||||
|
||||
Custom render by using `itemRender` slot.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:headers="headers"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Click to Upload
|
||||
</a-button>
|
||||
<template #itemRender="{ file, actions }">
|
||||
<a-space>
|
||||
<span :style="file.status === 'error' ? 'color: red' : ''">{{ file.name }}</span>
|
||||
<a href="javascript:;" @click="actions.download">download</a>
|
||||
<a href="javascript:;" @click="actions.remove">delete</a>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-upload>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { message } from 'ant-design-vue';
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
},
|
||||
setup() {
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`);
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
};
|
||||
|
||||
const fileList = ref<UploadProps['fileList']>([
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'xxx.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-2',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
response: 'Server Error 500', // custom error message to show
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]);
|
||||
return {
|
||||
fileList,
|
||||
headers: {
|
||||
authorization: 'authorization-text',
|
||||
},
|
||||
handleChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
76
components/upload/demo/customize-progress-bar.vue
Normal file
76
components/upload/demo/customize-progress-bar.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<docs>
|
||||
---
|
||||
order: 15
|
||||
title:
|
||||
zh-CN: 自定义进度条样式
|
||||
en-US: Customize Progress Bar
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `progress` 属性自定义进度条样式。
|
||||
|
||||
## en-US
|
||||
|
||||
Use `progress` for customize progress bar.
|
||||
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:headers="headers"
|
||||
:progress="progress"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Click to Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { message } from 'ant-design-vue';
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
},
|
||||
setup() {
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`);
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
};
|
||||
|
||||
const fileList = ref([]);
|
||||
const progress: UploadProps['progress'] = {
|
||||
strokeColor: {
|
||||
'0%': '#108ee9',
|
||||
'100%': '#87d068',
|
||||
},
|
||||
strokeWidth: 3,
|
||||
format: percent => `${parseFloat(percent.toFixed(2))}%`,
|
||||
class: 'test',
|
||||
};
|
||||
return {
|
||||
fileList,
|
||||
headers: {
|
||||
authorization: 'authorization-text',
|
||||
},
|
||||
handleChange,
|
||||
progress,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -8,11 +8,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `defaultFileList` 设置已上传的内容。
|
||||
使用 `fileList` 设置已上传的内容。
|
||||
|
||||
## en-US
|
||||
|
||||
Use `defaultFileList` for uploaded files when page init.
|
||||
Use `fileList` for uploaded files when page init.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
|
@ -10,13 +10,13 @@ title:
|
||||
|
||||
把文件拖入指定区域,完成上传,同样支持点击上传。
|
||||
|
||||
设置 `multiple` 后,在 `IE10+` 可以一次上传多个文件。
|
||||
设置 `multiple` 后,可以一次上传多个文件。
|
||||
|
||||
## en-US
|
||||
|
||||
You can drag files to a specific area, to upload. Alternatively, you can also upload by selecting.
|
||||
|
||||
We can upload serveral files at once in modern browsers by giving the input the `multiple` attribute.
|
||||
We can upload serveral files at once by giving the input the `multiple` attribute.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
@ -26,6 +26,7 @@ We can upload serveral files at once in modern browsers by giving the input the
|
||||
:multiple="true"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
@change="handleChange"
|
||||
@drop="handleDrop"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<inbox-outlined></inbox-outlined>
|
||||
@ -62,6 +63,9 @@ export default defineComponent({
|
||||
return {
|
||||
handleChange,
|
||||
fileList: ref([]),
|
||||
handleDrop: (e: DragEvent) => {
|
||||
console.log(e);
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -11,6 +11,11 @@
|
||||
<Directory />
|
||||
<PreviewFile />
|
||||
<TransformFile />
|
||||
<customizeProgressBarVue />
|
||||
<maxCountVue />
|
||||
<uploadCustomActionIconVue />
|
||||
<uploadPngOnlyVue />
|
||||
<customRenderVue />
|
||||
</demo-sort>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@ -25,6 +30,11 @@ import UploadManually from './upload-manually.vue';
|
||||
import Directory from './directory.vue';
|
||||
import PreviewFile from './preview-file.vue';
|
||||
import TransformFile from './transform-file.vue';
|
||||
import customizeProgressBarVue from './customize-progress-bar.vue';
|
||||
import maxCountVue from './max-count.vue';
|
||||
import uploadCustomActionIconVue from './upload-custom-action-icon.vue';
|
||||
import uploadPngOnlyVue from './upload-png-only.vue';
|
||||
import customRenderVue from './custom-render.vue';
|
||||
import CN from '../index.zh-CN.md';
|
||||
import US from '../index.en-US.md';
|
||||
import { defineComponent } from 'vue';
|
||||
@ -44,6 +54,11 @@ export default defineComponent({
|
||||
Directory,
|
||||
PreviewFile,
|
||||
TransformFile,
|
||||
customizeProgressBarVue,
|
||||
maxCountVue,
|
||||
uploadCustomActionIconVue,
|
||||
uploadPngOnlyVue,
|
||||
customRenderVue,
|
||||
},
|
||||
setup() {
|
||||
return {};
|
||||
|
63
components/upload/demo/max-count.vue
Normal file
63
components/upload/demo/max-count.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<docs>
|
||||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 限制数量
|
||||
en-US: Max Count
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 `maxCount` 限制上传数量。当为 `1` 时,始终用最新上传的代替当前。
|
||||
|
||||
## en-US
|
||||
|
||||
Limit files with `maxCount`. Will replace current one when `maxCount` is `1`.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<a-space direction="vertical" style="width: 100%" size="large">
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
list-type="picture"
|
||||
:max-count="1"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Upload (Max: 1)
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<a-upload
|
||||
v-model:file-list="fileList2"
|
||||
list-type="picture"
|
||||
:max-count="3"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Upload (Max: 3)
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-space>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadProps } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
},
|
||||
setup() {
|
||||
const fileList = ref<UploadProps['fileList']>([]);
|
||||
const fileList2 = ref<UploadProps['fileList']>([]);
|
||||
|
||||
return {
|
||||
fileList,
|
||||
fileList2,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -25,10 +25,10 @@ After users upload picture, the thumbnail will be shown in list. The upload butt
|
||||
>
|
||||
<div v-if="fileList.length < 8">
|
||||
<plus-outlined />
|
||||
<div class="ant-upload-text">Upload</div>
|
||||
<div style="margin-top: 8px">Upload</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
|
||||
<a-modal :visible="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel">
|
||||
<img alt="example" style="width: 100%" :src="previewImage" />
|
||||
</a-modal>
|
||||
</div>
|
||||
@ -36,7 +36,7 @@ After users upload picture, the thumbnail will be shown in list. The upload butt
|
||||
<script lang="ts">
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||
import type { UploadProps } from 'ant-design-vue';
|
||||
|
||||
function getBase64(file: File) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -52,8 +52,9 @@ export default defineComponent({
|
||||
PlusOutlined,
|
||||
},
|
||||
setup() {
|
||||
const previewVisible = ref<boolean>(false);
|
||||
const previewImage = ref<string | undefined>('');
|
||||
const previewVisible = ref(false);
|
||||
const previewImage = ref('');
|
||||
const previewTitle = ref('');
|
||||
|
||||
const fileList = ref<UploadProps['fileList']>([
|
||||
{
|
||||
@ -80,6 +81,13 @@ export default defineComponent({
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-xxx',
|
||||
percent: 50,
|
||||
name: 'image.png',
|
||||
status: 'uploading',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-5',
|
||||
name: 'image.png',
|
||||
@ -89,6 +97,7 @@ export default defineComponent({
|
||||
|
||||
const handleCancel = () => {
|
||||
previewVisible.value = false;
|
||||
previewTitle.value = '';
|
||||
};
|
||||
const handlePreview = async (file: UploadProps['fileList'][number]) => {
|
||||
if (!file.url && !file.preview) {
|
||||
@ -96,9 +105,7 @@ export default defineComponent({
|
||||
}
|
||||
previewImage.value = file.url || file.preview;
|
||||
previewVisible.value = true;
|
||||
};
|
||||
const handleChange = ({ fileList: newFileList }: UploadChangeParam) => {
|
||||
fileList.value = newFileList;
|
||||
previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
|
||||
};
|
||||
|
||||
return {
|
||||
@ -107,7 +114,7 @@ export default defineComponent({
|
||||
fileList,
|
||||
handleCancel,
|
||||
handlePreview,
|
||||
handleChange,
|
||||
previewTitle,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -8,11 +8,11 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
上传文件为图片,可展示本地缩略图。`IE8/9` 不支持浏览器本地缩略图展示([Ref](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL)),可以写 `thumbUrl` 属性来代替。
|
||||
上传文件为图片,可展示本地缩略图。
|
||||
|
||||
## en-US
|
||||
|
||||
If uploaded file is a picture, the thumbnail can be shown. `IE8/9` do not support local thumbnail show. Please use `thumbUrl` instead.
|
||||
If uploaded file is a picture, the thumbnail can be shown.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
@ -99,10 +99,7 @@ export default defineComponent({
|
||||
width: 200px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.upload-list-inline :deep(.ant-upload-animate-enter) {
|
||||
animation-name: uploadAnimateInlineIn;
|
||||
}
|
||||
.upload-list-inline :deep(.ant-upload-animate-leave) {
|
||||
animation-name: uploadAnimateInlineOut;
|
||||
.upload-list-inline [class*='-upload-list-rtl'] :deep(.ant-upload-list-item) {
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
|
@ -33,13 +33,14 @@ Customize local preview. Can handle with non-image format files such as video.
|
||||
<script lang="ts">
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadProps } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
},
|
||||
setup() {
|
||||
const previewFile = async (file: any): Promise<Response> => {
|
||||
const previewFile: UploadProps['previewFile'] = async file => {
|
||||
console.log('Your upload file:', file);
|
||||
// Your process logic. Here we just mock to the same file
|
||||
const res = await fetch('https://next.json-generator.com/api/json/get/4ytyBoLK8', {
|
||||
|
@ -20,7 +20,7 @@ Use `beforeUpload` for transform file before request such as add a watermark.
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:transform-file="transformFile"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
@ -32,33 +32,37 @@ Use `beforeUpload` for transform file before request such as add a watermark.
|
||||
<script lang="ts">
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadProps } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
},
|
||||
setup() {
|
||||
const transformFile = (file: any) => {
|
||||
const beforeUpload: UploadProps['beforeUpload'] = file => {
|
||||
return new Promise(resolve => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const img: HTMLImageElement = document.createElement('img');
|
||||
img.src = reader.result as string;
|
||||
img.onload = () => {
|
||||
const ctx: CanvasRenderingContext2D = canvas.getContext('2d')!;
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = img.naturalWidth;
|
||||
canvas.height = img.naturalHeight;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
ctx.fillStyle = 'red';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText('Ant Design', 20, 20);
|
||||
ctx.font = '33px Arial';
|
||||
ctx.fillText('Ant Design Vue', 20, 20);
|
||||
canvas.toBlob(resolve);
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
return {
|
||||
transformFile,
|
||||
beforeUpload,
|
||||
fileList: ref([]),
|
||||
};
|
||||
},
|
||||
|
81
components/upload/demo/upload-custom-action-icon.vue
Normal file
81
components/upload/demo/upload-custom-action-icon.vue
Normal file
@ -0,0 +1,81 @@
|
||||
<docs>
|
||||
---
|
||||
order: 12
|
||||
title:
|
||||
zh-CN: 自定义交互图标
|
||||
en-US: custom action icon
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用相应插槽设置列表交互图标。
|
||||
|
||||
## en-US
|
||||
|
||||
Use slot for custom action icons of files.
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:show-upload-list="{ showDownloadIcon: true, showRemoveIcon: true }"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Upload
|
||||
</a-button>
|
||||
<template #downloadIcon>download</template>
|
||||
<template #removeIcon><StarOutlined @click="handleClick"></StarOutlined></template>
|
||||
</a-upload>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { UploadOutlined, StarOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
StarOutlined,
|
||||
},
|
||||
setup() {
|
||||
const fileList = ref<UploadProps['fileList']>([
|
||||
{
|
||||
uid: '1',
|
||||
name: 'xxx.png',
|
||||
status: 'done',
|
||||
response: 'Server Error 500', // custom error message to show
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
},
|
||||
{
|
||||
uid: '2',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/yyy.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
response: 'Server Error 500', // custom error message to show
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]);
|
||||
|
||||
const handleChange = ({ file, fileList }: UploadChangeParam) => {
|
||||
if (file.status !== 'uploading') {
|
||||
console.log(file, fileList);
|
||||
}
|
||||
};
|
||||
return {
|
||||
fileList,
|
||||
handleChange,
|
||||
handleClick: (e: MouseEvent) => {
|
||||
console.log(e, 'custom removeIcon event');
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -17,7 +17,7 @@ Upload files manually after `beforeUpload` returns `false`.
|
||||
|
||||
<template>
|
||||
<div class="clearfix">
|
||||
<a-upload :file-list="fileList" :remove="handleRemove" :before-upload="beforeUpload">
|
||||
<a-upload :file-list="fileList" :before-upload="beforeUpload" @remove="handleRemove">
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Select File
|
||||
|
85
components/upload/demo/upload-png-only.vue
Normal file
85
components/upload/demo/upload-png-only.vue
Normal file
@ -0,0 +1,85 @@
|
||||
<docs>
|
||||
---
|
||||
order: 7.1
|
||||
title:
|
||||
zh-CN: 只上传 png 图片
|
||||
en-US: Upload png file only
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
`beforeUpload` 返回 `false` 或 `Promise.reject` 时,只用于拦截上传行为,不会阻止文件进入上传列表([原因](https://github.com/ant-design/ant-design/issues/15561#issuecomment-475108235))。如果需要阻止列表展现,可以通过返回 `Upload.LIST_IGNORE` 实现。
|
||||
|
||||
## en-US
|
||||
|
||||
`beforeUpload` only prevent upload behavior when return false or reject promise, the prevented file would still show in file list. Here is the example you can keep prevented files out of list by return `UPLOAD.LIST_IGNORE`.
|
||||
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
||||
:before-upload="beforeUpload"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
Upload png only
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
|
||||
import { message, Upload } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UploadOutlined,
|
||||
},
|
||||
setup() {
|
||||
const fileList = ref<UploadProps['fileList']>([
|
||||
{
|
||||
uid: '1',
|
||||
name: 'xxx.png',
|
||||
status: 'done',
|
||||
response: 'Server Error 500', // custom error message to show
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
},
|
||||
{
|
||||
uid: '2',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/yyy.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
response: 'Server Error 500', // custom error message to show
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]);
|
||||
|
||||
const handleChange = ({ file, fileList }: UploadChangeParam) => {
|
||||
if (file.status !== 'uploading') {
|
||||
console.log(file, fileList);
|
||||
}
|
||||
};
|
||||
const beforeUpload: UploadProps['beforeUpload'] = file => {
|
||||
const isPNG = file.type === 'image/png';
|
||||
if (!isPNG) {
|
||||
message.error(`${file.name} is not a png file`);
|
||||
}
|
||||
return isPNG || Upload.LIST_IGNORE;
|
||||
};
|
||||
return {
|
||||
fileList,
|
||||
handleChange,
|
||||
beforeUpload,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -18,12 +18,12 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
||||
## API
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| accept | File types that can be accepted. See [input accept Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept) | string | - | |
|
||||
| action | Uploading URL | string\|(file) => `Promise` | - | |
|
||||
| method | http method of upload request | string | `post` | 1.5.0 |
|
||||
| directory | support upload whole directory ([caniuse](https://caniuse.com/#feat=input-file-directory)) | boolean | false | |
|
||||
| beforeUpload | Hook function which will be executed before uploading. Uploading will be stopped with `false` or a rejected Promise returned. **Warning:this function is not supported in IE9**。 | (file, fileList) => `boolean | Promise` | - | |
|
||||
| beforeUpload | Hook function which will be executed before uploading. Uploading will be stopped with `false` or a rejected Promise returned. | (file, fileList) => `boolean | Promise` | - | |
|
||||
| customRequest | override for the default xhr behavior allowing for additional customization and ability to implement your own XMLHttpRequest | Function | - | |
|
||||
| data | Uploading params or function which can return uploading params. | object\|function(file) | - | |
|
||||
| disabled | disable upload button | boolean | false | |
|
||||
@ -33,12 +33,20 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
||||
| multiple | Whether to support selected multiple file. `IE10+` supported. You can select multiple files with CTRL holding down while multiple is set to be true | boolean | false | |
|
||||
| name | The name of uploading file | string | `file` | |
|
||||
| previewFile | Customize preview file logic | (file: File \| Blob) => Promise<dataURL: string> | - | 1.5.0 |
|
||||
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon` and `showRemoveIcon` individually | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true | |
|
||||
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon` and `showRemoveIcon` individually | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: booleanshowDownloadIcon?: boolean } | true | showDownloadIcon(3.0) |
|
||||
| supportServerRender | Need to be turned on while the server side is rendering. | boolean | false | |
|
||||
| withCredentials | ajax upload with cookie sent | boolean | false | |
|
||||
| openFileDialogOnClick | click open file dialog | boolean | true | |
|
||||
| remove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is `false` or a Promise which resolve(false) or reject. | Function(file): `boolean | Promise` | - | |
|
||||
| transformFile | Customize transform file before request | Function(file): `string | Blob | File | Promise<string | Blob | File>` | - | 1.5.0 |
|
||||
| directory | Support upload whole directory([caniuse](https://caniuse.com/#feat=input-file-directory)) | boolean | false | 3.0 |
|
||||
| iconRender | Custom show icon | v-slot:iconRender="{file: UploadFile, listType?: UploadListType}" | - | 3.0 |
|
||||
| isImageUrl | Customize if render <img /> in thumbnail | (file: UploadFile) => boolean | - | 3.0 |
|
||||
| itemRender | Custom item of uploadList | v-slot:itemRender="{originNode: ReactElement, file: UploadFile, fileList: object\[], actions: { download: function, preview: function, remove: function }" | - | 3.0 |
|
||||
| maxCount | Limit the number of uploaded files. Will replace current one when `maxCount` is `1` | number | - | 3.0 |
|
||||
| openFileDialogOnClick | Click open file dialog | boolean | true | 3.0 |
|
||||
| progress | Custom progress bar | [ProgressProps](/components/progress/#API) (support `type="line"` only) | { strokeWidth: 2, showInfo: false } | 3.0 |
|
||||
| previewIcon | custom preview icon | v-slot:iconRender="{file: UploadFile}" | - | 3.0 |
|
||||
| removeIcon | custom remove icon | v-slot:iconRender="{file: UploadFile}" | - | 3.0 |
|
||||
| downloadIcon | custom download icon | v-slot:iconRender="{file: UploadFile}" | - | 3.0 |
|
||||
|
||||
### events
|
||||
|
||||
@ -48,6 +56,21 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
||||
| preview | A callback function, will be executed when file link or preview icon is clicked. | Function(file) | - | |
|
||||
| download | Click the method to download the file, pass the method to perform the method logic, do not pass the default jump to the new TAB. | Function(file): void | Jump to new TAB | 1.5.0 |
|
||||
| reject | A callback function, will be executed when drop files is not accept. | Function(fileList) | - | |
|
||||
| drop | A callback function executed when files are dragged and dropped into upload area | (event: DragEvent) => void | - | 3.0 |
|
||||
| remove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is false or a Promise which resolve(false) or reject | function(file): boolean \| Promise | - | 3.0 |
|
||||
|
||||
### UploadFile
|
||||
|
||||
Extends File with additional props.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| name | File name | string | - |
|
||||
| percent | Upload progress percent | number | - |
|
||||
| status | Upload status. Show different style when configured | `error` \| `success` \| `done` \| `uploading` \| `removed` | - |
|
||||
| thumbUrl | Thumb image url | string | - |
|
||||
| uid | unique id. Will auto generate when not provided | string | - |
|
||||
| url | Download url | string | - |
|
||||
|
||||
### change
|
||||
|
||||
@ -78,3 +101,26 @@ When uploading state change, it returns:
|
||||
|
||||
2. `fileList` current list of files
|
||||
3. `event` response from server, including uploading progress, supported by advanced browsers.
|
||||
|
||||
## FAQ
|
||||
|
||||
### How to implement upload server side?
|
||||
|
||||
- You can consult [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload/wiki#server-side) about how to implement server side upload interface.
|
||||
- There is a mock example of [express](https://github.com/react-component/upload/blob/master/server.js) in rc-upload.
|
||||
|
||||
### I want to display download links.
|
||||
|
||||
Please set property `url` of each item in `fileList` to control content of link.
|
||||
|
||||
### How to use `customRequest`?
|
||||
|
||||
See <https://github.com/react-component/upload#customrequest>.
|
||||
|
||||
### Why `fileList` in control will not trigger `change` `status` update when file not in the list?
|
||||
|
||||
`change` only trigger when file in the list, it will ignore left events when removed from the list. Please note that there exist bug which makes event still trigger even the file is not in the list before `3.0.0-beta.10`.
|
||||
|
||||
### Why sometime `change` return File object and sometime return { originFileObj: File }?
|
||||
|
||||
For compatible case, we return File object when `beforeUpload` return `false`. It will merge to `{ originFileObj: File }` in next major version. Current version is compatible to get origin file by `info.file.originFileObj`. You can change this before major release.
|
||||
|
@ -1,21 +1,18 @@
|
||||
import type { App, Plugin } from 'vue';
|
||||
import Upload from './Upload';
|
||||
import type { App } from 'vue';
|
||||
import Upload, { LIST_IGNORE } from './Upload';
|
||||
import Dragger from './Dragger';
|
||||
|
||||
export type { UploadProps, UploadListProps, UploadChangeParam } from './interface';
|
||||
|
||||
Upload.Dragger = Dragger;
|
||||
export type { UploadProps, UploadListProps, UploadChangeParam, UploadFile } from './interface';
|
||||
|
||||
/* istanbul ignore next */
|
||||
Upload.install = function (app: App) {
|
||||
app.component(Upload.name, Upload);
|
||||
app.component(Dragger.name, Dragger);
|
||||
return app;
|
||||
};
|
||||
|
||||
export const UploadDragger = Dragger;
|
||||
|
||||
export default Upload as typeof Upload &
|
||||
Plugin & {
|
||||
readonly Dragger: typeof Dragger;
|
||||
};
|
||||
export default Object.assign(Upload, {
|
||||
Dragger,
|
||||
LIST_IGNORE,
|
||||
install(app: App) {
|
||||
app.component(Upload.name, Upload);
|
||||
app.component(Dragger.name, Dragger);
|
||||
return app;
|
||||
},
|
||||
});
|
||||
|
@ -19,12 +19,12 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| accept | 接受上传的文件类型, 详见 [input accept Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept) | string | 无 | |
|
||||
| action | 上传的地址 | string\|(file) => `Promise` | 无 | |
|
||||
| method | 上传请求的 http method | string | `post` | 1.5.0 |
|
||||
| directory | 支持上传文件夹([caniuse](https://caniuse.com/#feat=input-file-directory)) | boolean | false | |
|
||||
| beforeUpload | 上传文件之前的钩子,参数为上传的文件,若返回 `false` 则停止上传。支持返回一个 Promise 对象,Promise 对象 reject 时则停止上传,resolve 时开始上传( resolve 传入 `File` 或 `Blob` 对象则上传 resolve 传入对象)。**注意:IE9 不支持该方法**。 | (file, fileList) => `boolean | Promise` | 无 | |
|
||||
| beforeUpload | 上传文件之前的钩子,参数为上传的文件,若返回 `false` 则停止上传。支持返回一个 Promise 对象,Promise 对象 reject 时则停止上传,resolve 时开始上传( resolve 传入 `File` 或 `Blob` 对象则上传 resolve 传入对象)。 | (file, fileList) => `boolean | Promise` | 无 | |
|
||||
| customRequest | 通过覆盖默认的上传行为,可以自定义自己的上传实现 | Function | 无 | |
|
||||
| data | 上传所需参数或返回上传参数的方法 | object\|(file) => object | 无 | |
|
||||
| disabled | 是否禁用 | boolean | false | |
|
||||
@ -34,12 +34,20 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
||||
| multiple | 是否支持多选文件,`ie10+` 支持。开启后按住 ctrl 可选择多个文件。 | boolean | false | |
|
||||
| name | 发到后台的文件参数名 | string | `file` | |
|
||||
| previewFile | 自定义文件预览逻辑 | (file: File \| Blob) => Promise<dataURL: string> | 无 | 1.5.0 |
|
||||
| showUploadList | 是否展示 uploadList, 可设为一个对象,用于单独设定 showPreviewIcon 和 showRemoveIcon | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true | |
|
||||
| showUploadList | 是否展示 uploadList, 可设为一个对象,用于单独设定 showPreviewIcon 和 showRemoveIcon | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean } | true | showDownloadIcon(3.0) |
|
||||
| supportServerRender | 服务端渲染时需要打开这个 | boolean | false | |
|
||||
| withCredentials | 上传请求时是否携带 cookie | boolean | false | |
|
||||
| openFileDialogOnClick | 点击打开文件对话框 | boolean | true | |
|
||||
| remove | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除。 | Function(file): `boolean | Promise` | 无 | |
|
||||
| transformFile | 在上传之前转换文件。支持返回一个 Promise 对象 | Function(file): `string | Blob | File | Promise<string | Blob | File>` | 无 | 1.5.0 |
|
||||
| directory | 支持上传文件夹([caniuse](https://caniuse.com/#feat=input-file-directory)) | boolean | false | 3.0 |
|
||||
| iconRender | 自定义显示 icon | v-slot:iconRender="{file: UploadFile, listType?: UploadListType}" | - | 3.0 |
|
||||
| isImageUrl | 自定义缩略图是否使用 <img /> 标签进行显示 | (file: UploadFile) => boolean | - | 3.0 |
|
||||
| itemRender | 自定义上传列表项 | v-slot:itemRender="{originNode: ReactElement, file: UploadFile, fileList: object\[], actions: { download: function, preview: function, remove: function }" | - | 3.0 |
|
||||
| maxCount | 限制上传数量。当为 1 时,始终用最新上传的文件代替当前文件 | number | - | 3.0 |
|
||||
| openFileDialogOnClick | 点击打开文件对话框 | boolean | true | 3.0 |
|
||||
| progress | 自定义进度条样式 | [ProgressProps](/components/progress/#API)(仅支持 `type="line"`) | { strokeWidth: 2, showInfo: false } | 3.0 |
|
||||
| previewIcon | 自定义预览 icon | v-slot:iconRender="{file: UploadFile}" | - | 3.0 |
|
||||
| removeIcon | 自定义删除 icon | v-slot:iconRender="{file: UploadFile}" | - | 3.0 |
|
||||
| downloadIcon | 自定义下载 icon | v-slot:iconRender="{file: UploadFile}" | - | 3.0 |
|
||||
|
||||
### 事件
|
||||
|
||||
@ -49,6 +57,21 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
||||
| preview | 点击文件链接或预览图标时的回调 | Function(file) | 无 | |
|
||||
| download | 点击下载文件时的回调,如果没有指定,则默认跳转到文件 url 对应的标签页。 | Function(file): void | 跳转新标签页 | 1.5.0 |
|
||||
| reject | 拖拽文件不符合 accept 类型时的回调 | Function(fileList) | 无 | |
|
||||
| drop | 当文件被拖入上传区域时执行的回调功能 | (event: DragEvent) => void | - | 3.0 |
|
||||
| remove | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除 | function(file): boolean \| Promise | - | 3.0 |
|
||||
|
||||
### UploadFile
|
||||
|
||||
继承自 File,附带额外属性用于渲染。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| name | 文件名 | string | - |
|
||||
| percent | 上传进度 | number | - |
|
||||
| status | 上传状态,不同状态展示颜色也会有所不同 | `error` \| `success` \| `done` \| `uploading` \| `removed` | - |
|
||||
| thumbUrl | 缩略图地址 | string | - |
|
||||
| uid | 唯一标识符,不设置时会自动生成 | string | - |
|
||||
| url | 下载地址 | string | - |
|
||||
|
||||
### change
|
||||
|
||||
@ -79,3 +102,26 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
||||
|
||||
2. `fileList` 当前的文件列表。
|
||||
3. `event` 上传中的服务端响应内容,包含了上传进度等信息,高级浏览器支持。
|
||||
|
||||
## FAQ
|
||||
|
||||
### 服务端如何实现?
|
||||
|
||||
- 服务端上传接口实现可以参考 [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload/wiki#server-side)。
|
||||
- 如果要做本地 mock 可以参考这个 [express 的例子](https://github.com/react-component/upload/blob/master/server.js)。
|
||||
|
||||
### 如何显示下载链接?
|
||||
|
||||
请使用 fileList 属性设置数组项的 url 属性进行展示控制。
|
||||
|
||||
### `customRequest` 怎么使用?
|
||||
|
||||
请参考 <https://github.com/react-component/upload#customrequest>。
|
||||
|
||||
### 为何 `fileList` 受控时,上传不在列表中的文件不会触发 `onChange` 后续的 `status` 更新事件?
|
||||
|
||||
`onChange` 事件仅会作用于在列表中的文件,因而 `fileList` 不存在对应文件时后续事件会被忽略。请注意,在 `3.0.0-beta.10` 版本之前受控状态存在 bug 导致不在列表中的文件也会触发。
|
||||
|
||||
### `onChange` 为什么有时候返回 File 有时候返回 { originFileObj: File }?
|
||||
|
||||
历史原因,在 `beforeUpload` 返回 `false` 时,会返回 File 对象。在下个大版本我们会统一返回 `{ originFileObj: File }` 对象。当前版本已经兼容所有场景下 `info.file.originFileObj` 获取原 File 写法。你可以提前切换。
|
||||
|
@ -1,22 +1,21 @@
|
||||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
import { tuple } from '../_util/type';
|
||||
import PropsTypes from '../_util/vue-types';
|
||||
import type {
|
||||
RcFile as OriRcFile,
|
||||
UploadRequestOption as RcCustomRequestOptions,
|
||||
} from '../vc-upload/interface';
|
||||
import type { ProgressProps } from '../progress';
|
||||
import type { VueNode } from '../_util/type';
|
||||
import type { ExtractPropTypes, PropType, CSSProperties } from 'vue';
|
||||
|
||||
export const UploadFileStatus = PropsTypes.oneOf(
|
||||
tuple('error', 'success', 'done', 'uploading', 'removed'),
|
||||
);
|
||||
export interface FileType extends OriRcFile {
|
||||
readonly lastModifiedDate: Date;
|
||||
}
|
||||
|
||||
export type UploadFileStatus = 'error' | 'success' | 'done' | 'uploading' | 'removed';
|
||||
|
||||
export interface HttpRequestHeader {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface VcFile extends File {
|
||||
uid: string;
|
||||
readonly lastModifiedDate: Date;
|
||||
readonly webkitRelativePath: string;
|
||||
}
|
||||
|
||||
export type UploadFileStatus = 'error' | 'success' | 'done' | 'uploading' | 'removed';
|
||||
export interface UploadFile<T = any> {
|
||||
uid: string;
|
||||
size?: number;
|
||||
@ -28,7 +27,7 @@ export interface UploadFile<T = any> {
|
||||
status?: UploadFileStatus;
|
||||
percent?: number;
|
||||
thumbUrl?: string;
|
||||
originFileObj?: any;
|
||||
originFileObj?: FileType;
|
||||
response?: T;
|
||||
error?: any;
|
||||
linkProps?: any;
|
||||
@ -37,17 +36,23 @@ export interface UploadFile<T = any> {
|
||||
preview?: string;
|
||||
}
|
||||
|
||||
export interface UploadChangeParam<T extends object = UploadFile> {
|
||||
export interface InternalUploadFile<T = any> extends UploadFile<T> {
|
||||
originFileObj: FileType;
|
||||
}
|
||||
|
||||
export interface ShowUploadListInterface {
|
||||
showRemoveIcon?: boolean;
|
||||
showPreviewIcon?: boolean;
|
||||
showDownloadIcon?: boolean;
|
||||
}
|
||||
|
||||
export interface UploadChangeParam<T = UploadFile> {
|
||||
// https://github.com/ant-design/ant-design/issues/14420
|
||||
file: T;
|
||||
fileList: UploadFile[];
|
||||
event?: { percent: number };
|
||||
}
|
||||
|
||||
export const ShowUploadListInterface = PropsTypes.shape({
|
||||
showRemoveIcon: PropsTypes.looseBool,
|
||||
showPreviewIcon: PropsTypes.looseBool,
|
||||
}).loose;
|
||||
|
||||
export interface UploadLocale {
|
||||
uploading?: string;
|
||||
removeFile?: string;
|
||||
@ -56,61 +61,129 @@ export interface UploadLocale {
|
||||
previewFile?: string;
|
||||
}
|
||||
|
||||
export const uploadProps = {
|
||||
type: PropsTypes.oneOf(tuple('drag', 'select')),
|
||||
name: PropsTypes.string,
|
||||
defaultFileList: { type: Array as PropType<UploadFile[]> },
|
||||
fileList: { type: Array as PropType<UploadFile[]> },
|
||||
action: PropsTypes.oneOfType([PropsTypes.string, PropsTypes.func]),
|
||||
directory: PropsTypes.looseBool,
|
||||
data: PropsTypes.oneOfType([PropsTypes.object, PropsTypes.func]),
|
||||
method: PropsTypes.oneOf(tuple('POST', 'PUT', 'PATCH', 'post', 'put', 'patch')),
|
||||
headers: PropsTypes.object,
|
||||
showUploadList: PropsTypes.oneOfType([PropsTypes.looseBool, ShowUploadListInterface]),
|
||||
multiple: PropsTypes.looseBool,
|
||||
accept: PropsTypes.string,
|
||||
beforeUpload: PropsTypes.func,
|
||||
listType: PropsTypes.oneOf(tuple('text', 'picture', 'picture-card')),
|
||||
// className: PropsTypes.string,
|
||||
remove: PropsTypes.func,
|
||||
supportServerRender: PropsTypes.looseBool,
|
||||
// style: PropsTypes.object,
|
||||
disabled: PropsTypes.looseBool,
|
||||
prefixCls: PropsTypes.string,
|
||||
customRequest: PropsTypes.func,
|
||||
withCredentials: PropsTypes.looseBool,
|
||||
openFileDialogOnClick: PropsTypes.looseBool,
|
||||
locale: { type: Object as PropType<UploadLocale> },
|
||||
height: PropsTypes.number,
|
||||
id: PropsTypes.string,
|
||||
previewFile: PropsTypes.func,
|
||||
transformFile: PropsTypes.func,
|
||||
onChange: { type: Function as PropType<(info: UploadChangeParam) => void> },
|
||||
onPreview: { type: Function as PropType<(file: UploadFile) => void> },
|
||||
onRemove: {
|
||||
type: Function as PropType<(file: UploadFile) => void | boolean | Promise<void | boolean>>,
|
||||
},
|
||||
onDownload: { type: Function as PropType<(file: UploadFile) => void> },
|
||||
'onUpdate:fileList': { type: Function as PropType<(files: UploadFile[]) => void> },
|
||||
export type UploadType = 'drag' | 'select';
|
||||
export type UploadListType = 'text' | 'picture' | 'picture-card';
|
||||
export type UploadListProgressProps = Omit<ProgressProps, 'percent' | 'type'> & {
|
||||
class?: string;
|
||||
style?: CSSProperties;
|
||||
};
|
||||
|
||||
export type UploadProps = Partial<ExtractPropTypes<typeof uploadProps>>;
|
||||
export const uploadListProps = {
|
||||
listType: PropsTypes.oneOf(tuple('text', 'picture', 'picture-card')),
|
||||
// items: PropsTypes.arrayOf(UploadFile),
|
||||
items: { type: Array as PropType<UploadFile[]> },
|
||||
progressAttr: PropsTypes.object,
|
||||
prefixCls: PropsTypes.string,
|
||||
showRemoveIcon: PropsTypes.looseBool,
|
||||
showDownloadIcon: PropsTypes.looseBool,
|
||||
showPreviewIcon: PropsTypes.looseBool,
|
||||
locale: { type: Object as PropType<UploadLocale> },
|
||||
previewFile: PropsTypes.func,
|
||||
onPreview: { type: Function as PropType<(file: UploadFile) => void> },
|
||||
onRemove: {
|
||||
type: Function as PropType<(file: UploadFile) => void | boolean>,
|
||||
},
|
||||
onDownload: { type: Function as PropType<(file: UploadFile) => void> },
|
||||
};
|
||||
export type ItemRender<T = any> = (opt: {
|
||||
originNode: VueNode;
|
||||
file: UploadFile;
|
||||
fileList: Array<UploadFile<T>>;
|
||||
actions: {
|
||||
download: () => void;
|
||||
preview: () => void;
|
||||
remove: () => void;
|
||||
};
|
||||
}) => VueNode;
|
||||
|
||||
export type UploadListProps = Partial<ExtractPropTypes<typeof uploadListProps>>;
|
||||
type PreviewFileHandler = (file: FileType | Blob) => PromiseLike<string>;
|
||||
type TransformFileHandler = (
|
||||
file: FileType,
|
||||
) => string | Blob | FileType | PromiseLike<string | Blob | FileType>;
|
||||
type BeforeUploadValueType = void | boolean | string | Blob | FileType;
|
||||
|
||||
function uploadProps<T = any>() {
|
||||
return {
|
||||
capture: [Boolean, String] as PropType<boolean | 'user' | 'environment'>,
|
||||
type: String as PropType<UploadType>,
|
||||
name: String,
|
||||
defaultFileList: Array as PropType<Array<UploadFile<T>>>,
|
||||
fileList: Array as PropType<Array<UploadFile<T>>>,
|
||||
action: [String, Function] as PropType<
|
||||
string | ((file: FileType) => string) | ((file: FileType) => PromiseLike<string>)
|
||||
>,
|
||||
directory: { type: Boolean, default: undefined },
|
||||
data: [Object, Function] as PropType<
|
||||
| Record<string, unknown>
|
||||
| ((file: UploadFile<T>) => Record<string, unknown> | Promise<Record<string, unknown>>)
|
||||
>,
|
||||
method: String as PropType<'POST' | 'PUT' | 'PATCH' | 'post' | 'put' | 'patch'>,
|
||||
headers: Object as PropType<HttpRequestHeader>,
|
||||
showUploadList: {
|
||||
type: [Boolean, Object] as PropType<boolean | ShowUploadListInterface>,
|
||||
default: undefined as boolean | ShowUploadListInterface,
|
||||
},
|
||||
multiple: { type: Boolean, default: undefined },
|
||||
accept: String,
|
||||
beforeUpload: Function as PropType<
|
||||
(
|
||||
file: FileType,
|
||||
FileList: FileType[],
|
||||
) => BeforeUploadValueType | Promise<BeforeUploadValueType>
|
||||
>,
|
||||
onChange: Function as PropType<(info: UploadChangeParam<T>) => void>,
|
||||
'onUpdate:fileList': Function as PropType<(fileList: UploadChangeParam<T>['fileList']) => void>,
|
||||
onDrop: Function as PropType<(event: DragEvent) => void>,
|
||||
listType: String as PropType<UploadListType>,
|
||||
onPreview: Function as PropType<(file: UploadFile<T>) => void>,
|
||||
onDownload: Function as PropType<(file: UploadFile<T>) => void>,
|
||||
onReject: Function as PropType<(fileList: FileType[]) => void>,
|
||||
onRemove: Function as PropType<
|
||||
(file: UploadFile<T>) => void | boolean | Promise<void | boolean>
|
||||
>,
|
||||
/** @deprecated Please use `onRemove` directly */
|
||||
remove: Function as PropType<(file: UploadFile<T>) => void | boolean | Promise<void | boolean>>,
|
||||
supportServerRender: { type: Boolean, default: undefined },
|
||||
disabled: { type: Boolean, default: undefined },
|
||||
prefixCls: String,
|
||||
customRequest: Function as PropType<(options: RcCustomRequestOptions) => void>,
|
||||
withCredentials: { type: Boolean, default: undefined },
|
||||
openFileDialogOnClick: { type: Boolean, default: undefined },
|
||||
locale: { type: Object as PropType<UploadLocale>, default: undefined as UploadLocale },
|
||||
id: String,
|
||||
previewFile: Function as PropType<PreviewFileHandler>,
|
||||
/** @deprecated Please use `beforeUpload` directly */
|
||||
transformFile: Function as PropType<TransformFileHandler>,
|
||||
iconRender: Function as PropType<
|
||||
(opt: { file: UploadFile<T>; listType?: UploadListType }) => VueNode
|
||||
>,
|
||||
isImageUrl: Function as PropType<(file: UploadFile) => boolean>,
|
||||
progress: Object as PropType<UploadListProgressProps>,
|
||||
itemRender: Function as PropType<ItemRender<T>>,
|
||||
/** Config max count of `fileList`. Will replace current one when `maxCount` is 1 */
|
||||
maxCount: Number,
|
||||
height: [Number, String],
|
||||
removeIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
downloadIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
previewIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
};
|
||||
}
|
||||
|
||||
export type UploadProps = Partial<ExtractPropTypes<ReturnType<typeof uploadProps>>>;
|
||||
|
||||
export interface UploadState<T = any> {
|
||||
fileList: UploadFile<T>[];
|
||||
dragState: string;
|
||||
}
|
||||
|
||||
function uploadListProps<T = any>() {
|
||||
return {
|
||||
listType: String as PropType<UploadListType>,
|
||||
onPreview: Function as PropType<(file: UploadFile<T>) => void>,
|
||||
onDownload: Function as PropType<(file: UploadFile<T>) => void>,
|
||||
onRemove: Function as PropType<(file: UploadFile<T>) => void | boolean>,
|
||||
items: Array as PropType<Array<UploadFile<T>>>,
|
||||
progress: Object as PropType<UploadListProgressProps>,
|
||||
prefixCls: String as PropType<string>,
|
||||
showRemoveIcon: { type: Boolean, default: undefined },
|
||||
showDownloadIcon: { type: Boolean, default: undefined },
|
||||
showPreviewIcon: { type: Boolean, default: undefined },
|
||||
removeIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
downloadIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
previewIcon: Function as PropType<(opt: { file: UploadFile }) => VueNode>,
|
||||
locale: { type: Object as PropType<UploadLocale>, default: undefined as UploadLocale },
|
||||
previewFile: Function as PropType<PreviewFileHandler>,
|
||||
iconRender: Function as PropType<
|
||||
(opt: { file: UploadFile<T>; listType?: UploadListType }) => VueNode
|
||||
>,
|
||||
isImageUrl: Function as PropType<(file: UploadFile) => boolean>,
|
||||
appendAction: Function as PropType<() => VueNode>,
|
||||
itemRender: Function as PropType<ItemRender<T>>,
|
||||
};
|
||||
}
|
||||
|
||||
export type UploadListProps = Partial<ExtractPropTypes<ReturnType<typeof uploadListProps>>>;
|
||||
export { uploadProps, uploadListProps };
|
||||
|
@ -34,8 +34,6 @@
|
||||
}
|
||||
|
||||
&&-select-picture-card {
|
||||
display: table;
|
||||
float: left;
|
||||
width: @upload-picture-card-size;
|
||||
height: @upload-picture-card-size;
|
||||
margin-right: 8px;
|
||||
@ -46,19 +44,21 @@
|
||||
border: @border-width-base dashed @border-color-base;
|
||||
border-radius: @border-radius-base;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.3s ease;
|
||||
transition: border-color 0.3s;
|
||||
|
||||
> .@{upload-prefix-cls} {
|
||||
display: table-cell;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: @primary-color;
|
||||
.@{upload-prefix-cls}-disabled& {
|
||||
border-color: @border-color-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@
|
||||
transition: border-color 0.3s;
|
||||
|
||||
.@{upload-prefix-cls} {
|
||||
padding: 16px 0;
|
||||
padding: @padding-md 0;
|
||||
}
|
||||
|
||||
&.@{upload-prefix-cls}-drag-hover:not(.@{upload-prefix-cls}-disabled) {
|
||||
@ -116,10 +116,12 @@
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-plus {
|
||||
color: @disabled-color;
|
||||
font-size: 30px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
@ -140,52 +142,55 @@
|
||||
.@{upload-prefix-cls}-list {
|
||||
.reset-component();
|
||||
.clearfix();
|
||||
&-item-list-type-text {
|
||||
&:hover {
|
||||
.@{upload-prefix-cls}-list-item-name-icon-count-1 {
|
||||
padding-right: 14px;
|
||||
}
|
||||
.@{upload-prefix-cls}-list-item-name-icon-count-2 {
|
||||
padding-right: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
line-height: @line-height-base;
|
||||
|
||||
// ============================ Item ============================
|
||||
&-item {
|
||||
position: relative;
|
||||
height: 22px;
|
||||
margin-top: 8px;
|
||||
height: @line-height-base * @font-size-base;
|
||||
margin-top: @margin-xs;
|
||||
font-size: @font-size-base;
|
||||
|
||||
&-name {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding-left: @font-size-base + 8px;
|
||||
overflow: hidden;
|
||||
line-height: @line-height-base;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&-name-icon-count-1 {
|
||||
padding-right: 14px;
|
||||
}
|
||||
|
||||
&-card-actions {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
&.picture {
|
||||
top: 25px;
|
||||
|
||||
&-btn {
|
||||
opacity: 0;
|
||||
}
|
||||
&-btn.@{ant-prefix}-btn-sm {
|
||||
height: 20px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&.picture {
|
||||
top: 22px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
&-btn:focus,
|
||||
&.picture &-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
.anticon {
|
||||
padding-right: 6px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
color: @upload-actions-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
height: 100%;
|
||||
padding: 0 12px 0 4px;
|
||||
padding: 0 4px;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
> span {
|
||||
@ -195,25 +200,27 @@
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-loading,
|
||||
.@{iconfont-css-prefix}-paper-clip {
|
||||
position: absolute;
|
||||
top: (@font-size-base / 2) - 2px;
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
.@{upload-prefix-cls}-text-icon {
|
||||
.@{iconfont-css-prefix} {
|
||||
position: absolute;
|
||||
top: (@font-size-base / 2) - 2px;
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-close {
|
||||
.iconfont-size-under-12px(10px);
|
||||
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 4px;
|
||||
color: @text-color-secondary;
|
||||
font-size: 10px;
|
||||
line-height: 0;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: @text-color;
|
||||
}
|
||||
@ -227,21 +234,24 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:hover &-card-actions {
|
||||
&:hover &-card-actions-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-error,
|
||||
&-error .@{iconfont-css-prefix}-paper-clip,
|
||||
&-error .@{upload-prefix-cls}-text-icon > .@{iconfont-css-prefix},
|
||||
&-error &-name {
|
||||
color: @error-color;
|
||||
}
|
||||
|
||||
&-error &-card-actions {
|
||||
.anticon {
|
||||
.@{iconfont-css-prefix} {
|
||||
color: @error-color;
|
||||
}
|
||||
opacity: 1;
|
||||
|
||||
&-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&-progress {
|
||||
@ -254,17 +264,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
// =================== Picture & Picture Card ===================
|
||||
&-picture,
|
||||
&-picture-card {
|
||||
.@{upload-item} {
|
||||
position: relative;
|
||||
height: 66px;
|
||||
padding: 8px;
|
||||
padding: @padding-xs;
|
||||
border: @border-width-base @upload-picture-card-border-style @border-color-base;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&-error {
|
||||
border-color: @error-color;
|
||||
}
|
||||
@ -283,15 +296,30 @@
|
||||
}
|
||||
|
||||
.@{upload-item}-thumbnail {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 26px;
|
||||
line-height: 54px;
|
||||
line-height: 60px;
|
||||
text-align: center;
|
||||
opacity: 0.8;
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the color of the error icon : https://github.com/ant-design/ant-design/pull/24160
|
||||
.@{upload-item}-error .@{upload-item}-thumbnail {
|
||||
.@{iconfont-css-prefix} {
|
||||
svg path {
|
||||
&[fill='#e6f7ff'] {
|
||||
fill: @error-color-deprecated-bg;
|
||||
}
|
||||
|
||||
&[fill='#1890ff'] {
|
||||
fill: @error-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-icon {
|
||||
@ -300,6 +328,10 @@
|
||||
left: 50%;
|
||||
font-size: 26px;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-image {
|
||||
@ -327,16 +359,8 @@
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.@{upload-item}-name-icon-count-1 {
|
||||
padding-right: 18px;
|
||||
}
|
||||
|
||||
.@{upload-item}-name-icon-count-2 {
|
||||
padding-right: 36px;
|
||||
}
|
||||
|
||||
.@{upload-item}-uploading .@{upload-item}-name {
|
||||
line-height: 28px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.@{upload-item}-progress {
|
||||
@ -355,21 +379,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== Picture Card ========================
|
||||
&-picture-card {
|
||||
&-container {
|
||||
display: inline-block;
|
||||
width: @upload-picture-card-size;
|
||||
height: @upload-picture-card-size;
|
||||
margin: 0 @margin-xs @margin-xs 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
&.@{upload-prefix-cls}-list::after {
|
||||
display: none;
|
||||
}
|
||||
&-container {
|
||||
float: left;
|
||||
width: @upload-picture-card-size;
|
||||
height: @upload-picture-card-size;
|
||||
margin: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.@{upload-item} {
|
||||
float: left;
|
||||
width: @upload-picture-card-size;
|
||||
height: @upload-picture-card-size;
|
||||
margin: 0 8px 8px 0;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.@{upload-item}-info {
|
||||
@ -413,6 +439,7 @@
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: @text-color-inverse;
|
||||
}
|
||||
@ -430,7 +457,7 @@
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.@{upload-item}-name {
|
||||
@ -441,7 +468,7 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.anticon-picture + .@{upload-item}-name {
|
||||
.@{upload-item}-file + .@{upload-item}-name {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
display: block;
|
||||
@ -454,46 +481,82 @@
|
||||
|
||||
.@{upload-item}-info {
|
||||
height: auto;
|
||||
|
||||
&::before,
|
||||
.@{iconfont-css-prefix}-eye-o,
|
||||
.@{iconfont-css-prefix}-eye,
|
||||
.@{iconfont-css-prefix}-delete {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
margin-top: 18px;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-progress {
|
||||
bottom: 32px;
|
||||
width: calc(100% - 14px);
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-prefix-cls}-success-icon {
|
||||
color: @success-color;
|
||||
font-weight: bold;
|
||||
// ======================= Picture & Text =======================
|
||||
&-text,
|
||||
&-picture {
|
||||
&-container {
|
||||
transition: opacity @animation-duration-slow, height @animation-duration-slow;
|
||||
|
||||
&::before {
|
||||
display: table;
|
||||
width: 0;
|
||||
height: 0;
|
||||
content: '';
|
||||
}
|
||||
|
||||
// Don't know why span here, just stretch it
|
||||
.@{upload-prefix-cls}-span {
|
||||
display: block;
|
||||
flex: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// text & picture no need this additional element.
|
||||
// But it used for picture-card, let's keep it.
|
||||
.@{upload-prefix-cls}-span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-name {
|
||||
flex: auto;
|
||||
margin: 0;
|
||||
padding: 0 @padding-xs;
|
||||
}
|
||||
|
||||
.@{upload-item}-card-actions {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-prefix-cls}-animate-enter,
|
||||
.@{upload-prefix-cls}-animate-leave,
|
||||
// ============================ Text ============================
|
||||
&-text {
|
||||
.@{upload-prefix-cls}-text-icon {
|
||||
.@{iconfont-css-prefix} {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =========================== Motion ===========================
|
||||
.@{upload-prefix-cls}-animate-inline-appear,
|
||||
.@{upload-prefix-cls}-animate-inline-enter,
|
||||
.@{upload-prefix-cls}-animate-inline-leave {
|
||||
animation-duration: 0.3s;
|
||||
animation-duration: @animation-duration-slow;
|
||||
animation-fill-mode: @ease-in-out-circ;
|
||||
}
|
||||
|
||||
.@{upload-prefix-cls}-animate-enter {
|
||||
animation-name: uploadAnimateIn;
|
||||
}
|
||||
|
||||
.@{upload-prefix-cls}-animate-leave {
|
||||
animation-name: uploadAnimateOut;
|
||||
}
|
||||
|
||||
.@{upload-prefix-cls}-animate-inline-appear,
|
||||
.@{upload-prefix-cls}-animate-inline-enter {
|
||||
animation-name: uploadAnimateInlineIn;
|
||||
}
|
||||
@ -503,24 +566,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes uploadAnimateIn {
|
||||
from {
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes uploadAnimateOut {
|
||||
to {
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes uploadAnimateInlineIn {
|
||||
from {
|
||||
width: 0;
|
||||
@ -540,3 +585,5 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@import './rtl';
|
||||
|
@ -2,5 +2,6 @@ import '../../style/index.less';
|
||||
import './index.less';
|
||||
|
||||
// style dependencies
|
||||
import '../../button/style';
|
||||
import '../../progress/style';
|
||||
import '../../tooltip/style';
|
179
components/upload/style/rtl.less
Normal file
179
components/upload/style/rtl.less
Normal file
@ -0,0 +1,179 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@upload-prefix-cls: ~'@{ant-prefix}-upload';
|
||||
@upload-item: ~'@{ant-prefix}-upload-list-item';
|
||||
|
||||
.@{upload-prefix-cls} {
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&&-select-picture-card {
|
||||
.@{upload-prefix-cls}-rtl& {
|
||||
margin-right: auto;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-prefix-cls}-list {
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-item-list-type-text {
|
||||
&:hover {
|
||||
.@{upload-prefix-cls}-list-item-name-icon-count-1 {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-right: 22px;
|
||||
padding-left: 14px;
|
||||
}
|
||||
}
|
||||
.@{upload-prefix-cls}-list-item-name-icon-count-2 {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-right: 22px;
|
||||
padding-left: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
&-name {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-right: @font-size-base + 8px;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-name-icon-count-1 {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-left: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&-card-actions {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
.@{iconfont-css-prefix} {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-right: 0;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding: 0 4px 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-close {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
right: auto;
|
||||
left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&-error &-card-actions {
|
||||
.@{iconfont-css-prefix} {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-right: 0;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-progress {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
padding-right: @font-size-base + 12px;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-picture,
|
||||
&-picture-card {
|
||||
.@{upload-item}-info {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.@{upload-item}-thumbnail {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
right: 8px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-icon {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
right: 50%;
|
||||
left: auto;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-name {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
margin: 0 8px 0 0;
|
||||
padding-right: 48px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-name-icon-count-1 {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
padding-right: 48px;
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-name-icon-count-2 {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
padding-right: 48px;
|
||||
padding-left: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-progress {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-close {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
right: auto;
|
||||
left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-picture-card {
|
||||
&-container {
|
||||
.@{upload-prefix-cls}-list-rtl & {
|
||||
margin: 0 0 @margin-xs @margin-xs;
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-actions {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
right: 50%;
|
||||
left: auto;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.@{upload-item}-file + .@{upload-item}-name {
|
||||
.@{upload-prefix-cls}-list-rtl& {
|
||||
margin: 8px 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,6 @@
|
||||
export function T() {
|
||||
return true;
|
||||
}
|
||||
import type { FileType, UploadFile, InternalUploadFile } from './interface';
|
||||
|
||||
// Fix IE file.status problem
|
||||
// via coping a new Object
|
||||
export function fileToObject(file) {
|
||||
export function file2Obj(file: FileType): InternalUploadFile {
|
||||
return {
|
||||
...file,
|
||||
lastModified: file.lastModified,
|
||||
@ -18,35 +14,24 @@ export function fileToObject(file) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成Progress percent: 0.1 -> 0.98
|
||||
* - for ie
|
||||
*/
|
||||
export function genPercentAdd() {
|
||||
let k = 0.1;
|
||||
const i = 0.01;
|
||||
const end = 0.98;
|
||||
return function (s) {
|
||||
let start = s;
|
||||
if (start >= end) {
|
||||
return start;
|
||||
}
|
||||
|
||||
start += k;
|
||||
k = k - i;
|
||||
if (k < 0.001) {
|
||||
k = 0.001;
|
||||
}
|
||||
return start;
|
||||
};
|
||||
/** Upload fileList. Replace file if exist or just push into it. */
|
||||
export function updateFileList(file: UploadFile<any>, fileList: UploadFile<any>[]) {
|
||||
const nextFileList = [...fileList];
|
||||
const fileIndex = nextFileList.findIndex(({ uid }: UploadFile) => uid === file.uid);
|
||||
if (fileIndex === -1) {
|
||||
nextFileList.push(file);
|
||||
} else {
|
||||
nextFileList[fileIndex] = file;
|
||||
}
|
||||
return nextFileList;
|
||||
}
|
||||
|
||||
export function getFileItem(file, fileList) {
|
||||
export function getFileItem(file: FileType, fileList: UploadFile[]) {
|
||||
const matchKey = file.uid !== undefined ? 'uid' : 'name';
|
||||
return fileList.filter(item => item[matchKey] === file[matchKey])[0];
|
||||
}
|
||||
|
||||
export function removeFileItem(file, fileList) {
|
||||
export function removeFileItem(file: UploadFile, fileList: UploadFile[]) {
|
||||
const matchKey = file.uid !== undefined ? 'uid' : 'name';
|
||||
const removed = fileList.filter(item => item[matchKey] !== file[matchKey]);
|
||||
if (removed.length === fileList.length) {
|
||||
@ -63,13 +48,13 @@ const extname = (url = '') => {
|
||||
return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0];
|
||||
};
|
||||
|
||||
const isImageFileType = type => !!type && type.indexOf('image/') === 0;
|
||||
const isImageFileType = (type: string): boolean => type.indexOf('image/') === 0;
|
||||
|
||||
export const isImageUrl = file => {
|
||||
if (isImageFileType(file.type)) {
|
||||
return true;
|
||||
export const isImageUrl = (file: UploadFile): boolean => {
|
||||
if (file.type && !file.thumbUrl) {
|
||||
return isImageFileType(file.type);
|
||||
}
|
||||
const url = file.thumbUrl || file.url;
|
||||
const url: string = (file.thumbUrl || file.url || '') as string;
|
||||
const extension = extname(url);
|
||||
if (
|
||||
/^data:image\//.test(url) ||
|
||||
@ -89,9 +74,9 @@ export const isImageUrl = file => {
|
||||
};
|
||||
|
||||
const MEASURE_SIZE = 200;
|
||||
export function previewImage(file) {
|
||||
export function previewImage(file: File | Blob): Promise<string> {
|
||||
return new Promise(resolve => {
|
||||
if (!isImageFileType(file.type)) {
|
||||
if (!file.type || !isImageFileType(file.type)) {
|
||||
resolve('');
|
||||
return;
|
||||
}
|
||||
@ -111,7 +96,7 @@ export function previewImage(file) {
|
||||
let offsetX = 0;
|
||||
let offsetY = 0;
|
||||
|
||||
if (width < height) {
|
||||
if (width > height) {
|
||||
drawHeight = height * (MEASURE_SIZE / width);
|
||||
offsetY = -(drawHeight - drawWidth) / 2;
|
||||
} else {
|
||||
@ -119,7 +104,7 @@ export function previewImage(file) {
|
||||
offsetX = -(drawWidth - drawHeight) / 2;
|
||||
}
|
||||
|
||||
ctx.drawImage(img, offsetX, offsetY, drawWidth, drawHeight);
|
||||
ctx!.drawImage(img, offsetX, offsetY, drawWidth, drawHeight);
|
||||
const dataURL = canvas.toDataURL();
|
||||
document.body.removeChild(canvas);
|
||||
|
317
components/vc-upload/AjaxUploader.tsx
Normal file
317
components/vc-upload/AjaxUploader.tsx
Normal file
@ -0,0 +1,317 @@
|
||||
import defaultRequest from './request';
|
||||
import getUid from './uid';
|
||||
import attrAccept from './attr-accept';
|
||||
import traverseFileTree from './traverseFileTree';
|
||||
import type {
|
||||
RcFile,
|
||||
UploadProgressEvent,
|
||||
UploadRequestError,
|
||||
BeforeUploadFileType,
|
||||
} from './interface';
|
||||
import { uploadProps } from './interface';
|
||||
import { defineComponent, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import type { ChangeEvent } from '../_util/EventInterface';
|
||||
import pickAttrs from '../_util/pickAttrs';
|
||||
import partition from 'lodash-es/partition';
|
||||
|
||||
interface ParsedFileInfo {
|
||||
origin: RcFile;
|
||||
action: string;
|
||||
data: Record<string, unknown>;
|
||||
parsedFile: RcFile;
|
||||
}
|
||||
export default defineComponent({
|
||||
name: 'AjaxUploader',
|
||||
inheritAttrs: false,
|
||||
props: uploadProps(),
|
||||
setup(props, { slots, attrs, expose }) {
|
||||
const uid = ref(getUid());
|
||||
const reqs: any = {};
|
||||
|
||||
const fileInput = ref<HTMLInputElement>();
|
||||
|
||||
let isMounted = false;
|
||||
|
||||
/**
|
||||
* Process file before upload. When all the file is ready, we start upload.
|
||||
*/
|
||||
const processFile = async (file: RcFile, fileList: RcFile[]): Promise<ParsedFileInfo> => {
|
||||
const { beforeUpload } = props;
|
||||
|
||||
let transformedFile: BeforeUploadFileType | void = file;
|
||||
if (beforeUpload) {
|
||||
try {
|
||||
transformedFile = await beforeUpload(file, fileList);
|
||||
} catch (e) {
|
||||
// Rejection will also trade as false
|
||||
transformedFile = false;
|
||||
}
|
||||
if (transformedFile === false) {
|
||||
return {
|
||||
origin: file,
|
||||
parsedFile: null,
|
||||
action: null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Get latest action
|
||||
const { action } = props;
|
||||
let mergedAction: string;
|
||||
if (typeof action === 'function') {
|
||||
mergedAction = await action(file);
|
||||
} else {
|
||||
mergedAction = action;
|
||||
}
|
||||
|
||||
// Get latest data
|
||||
const { data } = props;
|
||||
let mergedData: Record<string, unknown>;
|
||||
if (typeof data === 'function') {
|
||||
mergedData = await data(file);
|
||||
} else {
|
||||
mergedData = data;
|
||||
}
|
||||
|
||||
const parsedData =
|
||||
// string type is from legacy `transformFile`.
|
||||
// Not sure if this will work since no related test case works with it
|
||||
(typeof transformedFile === 'object' || typeof transformedFile === 'string') &&
|
||||
transformedFile
|
||||
? transformedFile
|
||||
: file;
|
||||
|
||||
let parsedFile: File;
|
||||
if (parsedData instanceof File) {
|
||||
parsedFile = parsedData;
|
||||
} else {
|
||||
parsedFile = new File([parsedData], file.name, { type: file.type });
|
||||
}
|
||||
|
||||
const mergedParsedFile: RcFile = parsedFile as RcFile;
|
||||
mergedParsedFile.uid = file.uid;
|
||||
|
||||
return {
|
||||
origin: file,
|
||||
data: mergedData,
|
||||
parsedFile: mergedParsedFile,
|
||||
action: mergedAction,
|
||||
};
|
||||
};
|
||||
|
||||
const post = ({ data, origin, action, parsedFile }: ParsedFileInfo) => {
|
||||
if (!isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { onStart, customRequest, name, headers, withCredentials, method } = props;
|
||||
|
||||
const { uid } = origin;
|
||||
const request = customRequest || defaultRequest;
|
||||
|
||||
const requestOption = {
|
||||
action,
|
||||
filename: name,
|
||||
data,
|
||||
file: parsedFile,
|
||||
headers,
|
||||
withCredentials,
|
||||
method: method || 'post',
|
||||
onProgress: (e: UploadProgressEvent) => {
|
||||
const { onProgress } = props;
|
||||
onProgress?.(e, parsedFile);
|
||||
},
|
||||
onSuccess: (ret: any, xhr: XMLHttpRequest) => {
|
||||
const { onSuccess } = props;
|
||||
onSuccess?.(ret, parsedFile, xhr);
|
||||
|
||||
delete reqs[uid];
|
||||
},
|
||||
onError: (err: UploadRequestError, ret: any) => {
|
||||
const { onError } = props;
|
||||
onError?.(err, ret, parsedFile);
|
||||
|
||||
delete reqs[uid];
|
||||
},
|
||||
};
|
||||
|
||||
onStart(origin);
|
||||
reqs[uid] = request(requestOption);
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
uid.value = getUid();
|
||||
};
|
||||
|
||||
const abort = (file?: any) => {
|
||||
if (file) {
|
||||
const uid = file.uid ? file.uid : file;
|
||||
if (reqs[uid] && reqs[uid].abort) {
|
||||
reqs[uid].abort();
|
||||
}
|
||||
delete reqs[uid];
|
||||
} else {
|
||||
Object.keys(reqs).forEach(uid => {
|
||||
if (reqs[uid] && reqs[uid].abort) {
|
||||
reqs[uid].abort();
|
||||
}
|
||||
delete reqs[uid];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
isMounted = true;
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
isMounted = false;
|
||||
abort();
|
||||
});
|
||||
const uploadFiles = (files: File[]) => {
|
||||
const originFiles = [...files] as RcFile[];
|
||||
const postFiles = originFiles.map((file: RcFile & { uid?: string }) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
file.uid = getUid();
|
||||
return processFile(file, originFiles);
|
||||
});
|
||||
|
||||
// Batch upload files
|
||||
Promise.all(postFiles).then(fileList => {
|
||||
const { onBatchStart } = props;
|
||||
|
||||
onBatchStart?.(fileList.map(({ origin, parsedFile }) => ({ file: origin, parsedFile })));
|
||||
|
||||
fileList
|
||||
.filter(file => file.parsedFile !== null)
|
||||
.forEach(file => {
|
||||
post(file);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onChange = (e: ChangeEvent) => {
|
||||
const { accept, directory } = props;
|
||||
const { files } = e.target as any;
|
||||
const acceptedFiles = [...files].filter(
|
||||
(file: RcFile) => !directory || attrAccept(file, accept),
|
||||
);
|
||||
uploadFiles(acceptedFiles);
|
||||
reset();
|
||||
};
|
||||
|
||||
const onClick = (e: MouseEvent | KeyboardEvent) => {
|
||||
const el = fileInput.value;
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
const { onClick } = props;
|
||||
// TODO
|
||||
// if (children && (children as any).type === 'button') {
|
||||
// const parent = el.parentNode as HTMLInputElement;
|
||||
// parent.focus();
|
||||
// parent.querySelector('button').blur();
|
||||
// }
|
||||
el.click();
|
||||
if (onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
const onFileDrop = (e: DragEvent) => {
|
||||
const { multiple } = props;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (e.type === 'dragover') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.directory) {
|
||||
traverseFileTree(
|
||||
Array.prototype.slice.call(e.dataTransfer.items),
|
||||
uploadFiles,
|
||||
(_file: RcFile) => attrAccept(_file, props.accept),
|
||||
);
|
||||
} else {
|
||||
const files: [RcFile[], RcFile[]] = partition(
|
||||
Array.prototype.slice.call(e.dataTransfer.files),
|
||||
(file: RcFile) => attrAccept(file, props.accept),
|
||||
);
|
||||
let successFiles = files[0];
|
||||
const errorFiles = files[1];
|
||||
if (multiple === false) {
|
||||
successFiles = successFiles.slice(0, 1);
|
||||
}
|
||||
|
||||
uploadFiles(successFiles);
|
||||
if (errorFiles.length && props.onReject) props.onReject(errorFiles);
|
||||
}
|
||||
};
|
||||
expose({
|
||||
abort,
|
||||
});
|
||||
return () => {
|
||||
const {
|
||||
componentTag: Tag,
|
||||
prefixCls,
|
||||
disabled,
|
||||
id,
|
||||
multiple,
|
||||
accept,
|
||||
capture,
|
||||
directory,
|
||||
openFileDialogOnClick,
|
||||
onMouseenter,
|
||||
onMouseleave,
|
||||
...otherProps
|
||||
} = props;
|
||||
const cls = {
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
[attrs.class as string]: !!attrs.class,
|
||||
};
|
||||
// because input don't have directory/webkitdirectory type declaration
|
||||
const dirProps: any = directory
|
||||
? { directory: 'directory', webkitdirectory: 'webkitdirectory' }
|
||||
: {};
|
||||
const events = disabled
|
||||
? {}
|
||||
: {
|
||||
onClick: openFileDialogOnClick ? onClick : () => {},
|
||||
onKeydown: openFileDialogOnClick ? onKeyDown : () => {},
|
||||
onMouseenter,
|
||||
onMouseleave,
|
||||
onDrop: onFileDrop,
|
||||
onDragover: onFileDrop,
|
||||
tabindex: '0',
|
||||
};
|
||||
return (
|
||||
<Tag {...events} class={cls} role="button" style={attrs.style}>
|
||||
<input
|
||||
{...pickAttrs(otherProps, { aria: true, data: true })}
|
||||
id={id}
|
||||
type="file"
|
||||
ref={fileInput}
|
||||
onClick={e => e.stopPropagation()} // https://github.com/ant-design/ant-design/issues/19948
|
||||
key={uid.value}
|
||||
style={{ display: 'none' }}
|
||||
accept={accept}
|
||||
{...dirProps}
|
||||
multiple={multiple}
|
||||
onChange={onChange}
|
||||
{...(capture != null ? { capture } : {})}
|
||||
/>
|
||||
{slots.default?.()}
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
41
components/vc-upload/Upload.tsx
Normal file
41
components/vc-upload/Upload.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { initDefaultProps } from '../_util/props-util';
|
||||
import AjaxUpload from './AjaxUploader';
|
||||
import type { RcFile } from './interface';
|
||||
import { uploadProps } from './interface';
|
||||
|
||||
function empty() {}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Upload',
|
||||
inheritAttrs: false,
|
||||
props: initDefaultProps(uploadProps(), {
|
||||
componentTag: 'span',
|
||||
prefixCls: 'rc-upload',
|
||||
data: {},
|
||||
headers: {},
|
||||
name: 'file',
|
||||
multipart: false,
|
||||
onStart: empty,
|
||||
onError: empty,
|
||||
onSuccess: empty,
|
||||
multiple: false,
|
||||
beforeUpload: null,
|
||||
customRequest: null,
|
||||
withCredentials: false,
|
||||
openFileDialogOnClick: true,
|
||||
}),
|
||||
setup(props, { slots, attrs, expose }) {
|
||||
const uploader = ref();
|
||||
|
||||
const abort = (file: RcFile) => {
|
||||
uploader.value?.abort(file);
|
||||
};
|
||||
expose({
|
||||
abort,
|
||||
});
|
||||
return () => {
|
||||
return <AjaxUpload {...props} {...attrs} v-slots={slots} ref={uploader} />;
|
||||
};
|
||||
},
|
||||
});
|
53
components/vc-upload/attr-accept.ts
Normal file
53
components/vc-upload/attr-accept.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { warning } from '../vc-util/warning';
|
||||
import type { RcFile } from './interface';
|
||||
|
||||
export default (file: RcFile, acceptedFiles: string | string[]) => {
|
||||
if (file && acceptedFiles) {
|
||||
const acceptedFilesArray = Array.isArray(acceptedFiles)
|
||||
? acceptedFiles
|
||||
: acceptedFiles.split(',');
|
||||
const fileName = file.name || '';
|
||||
const mimeType = file.type || '';
|
||||
const baseMimeType = mimeType.replace(/\/.*$/, '');
|
||||
|
||||
return acceptedFilesArray.some(type => {
|
||||
const validType = type.trim();
|
||||
// This is something like */*,* allow all files
|
||||
if (/^\*(\/\*)?$/.test(type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// like .jpg, .png
|
||||
if (validType.charAt(0) === '.') {
|
||||
const lowerFileName = fileName.toLowerCase();
|
||||
const lowerType = validType.toLowerCase();
|
||||
|
||||
let affixList = [lowerType];
|
||||
if (lowerType === '.jpg' || lowerType === '.jpeg') {
|
||||
affixList = ['.jpg', '.jpeg'];
|
||||
}
|
||||
|
||||
return affixList.some(affix => lowerFileName.endsWith(affix));
|
||||
}
|
||||
|
||||
// This is something like a image/* mime type
|
||||
if (/\/\*$/.test(validType)) {
|
||||
return baseMimeType === validType.replace(/\/.*$/, '');
|
||||
}
|
||||
|
||||
// Full match
|
||||
if (mimeType === validType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invalidate type should skip
|
||||
if (/^\w+$/.test(validType)) {
|
||||
warning(false, `Upload takes an invalidate 'accept' type '${validType}'.Skip for check.`);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
};
|
@ -1,4 +0,0 @@
|
||||
// rc-upload 2.9.4
|
||||
import upload from './src';
|
||||
|
||||
export default upload;
|
7
components/vc-upload/index.ts
Normal file
7
components/vc-upload/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
// rc-upload 4.3.3
|
||||
import Upload from './Upload';
|
||||
import type { UploadProps } from './interface';
|
||||
|
||||
export type { UploadProps };
|
||||
|
||||
export default Upload;
|
83
components/vc-upload/interface.tsx
Normal file
83
components/vc-upload/interface.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
|
||||
export type BeforeUploadFileType = File | Blob | boolean | string;
|
||||
|
||||
export type Action = string | ((file: RcFile) => string | PromiseLike<string>);
|
||||
|
||||
export const uploadProps = () => {
|
||||
return {
|
||||
capture: [Boolean, String] as PropType<boolean | 'user' | 'environment'>,
|
||||
multipart: { type: Boolean, default: undefined },
|
||||
name: String,
|
||||
disabled: { type: Boolean, default: undefined },
|
||||
componentTag: String as PropType<any>,
|
||||
action: [String, Function] as PropType<Action>,
|
||||
method: String as PropType<UploadRequestMethod>,
|
||||
directory: { type: Boolean, default: undefined },
|
||||
data: [Object, Function] as PropType<
|
||||
Record<string, unknown> | ((file: RcFile | string | Blob) => Record<string, unknown>)
|
||||
>,
|
||||
headers: Object as PropType<UploadRequestHeader>,
|
||||
accept: String,
|
||||
multiple: { type: Boolean, default: undefined },
|
||||
onBatchStart: Function as PropType<
|
||||
(fileList: { file: RcFile; parsedFile: Exclude<BeforeUploadFileType, boolean> }[]) => void
|
||||
>,
|
||||
onReject: Function as PropType<(fileList: RcFile[]) => void>,
|
||||
onStart: Function as PropType<(file: RcFile) => void>,
|
||||
onError: Function as PropType<
|
||||
(error: Error, ret: Record<string, unknown>, file: RcFile) => void
|
||||
>,
|
||||
onSuccess: Function as PropType<
|
||||
(response: Record<string, unknown>, file: RcFile, xhr: XMLHttpRequest) => void
|
||||
>,
|
||||
onProgress: Function as PropType<(event: UploadProgressEvent, file: RcFile) => void>,
|
||||
beforeUpload: Function as PropType<
|
||||
(
|
||||
file: RcFile,
|
||||
FileList: RcFile[],
|
||||
) => BeforeUploadFileType | Promise<void | BeforeUploadFileType>
|
||||
>,
|
||||
customRequest: Function as PropType<(option: UploadRequestOption) => void>,
|
||||
withCredentials: { type: Boolean, default: undefined },
|
||||
openFileDialogOnClick: { type: Boolean, default: undefined },
|
||||
prefixCls: String,
|
||||
id: String,
|
||||
onMouseenter: Function as PropType<(e: MouseEvent) => void>,
|
||||
onMouseleave: Function as PropType<(e: MouseEvent) => void>,
|
||||
onClick: Function as PropType<(e: MouseEvent | KeyboardEvent) => void>,
|
||||
};
|
||||
};
|
||||
|
||||
export type UploadProps = Partial<ExtractPropTypes<ReturnType<typeof uploadProps>>>;
|
||||
|
||||
export interface UploadProgressEvent extends Partial<ProgressEvent> {
|
||||
percent?: number;
|
||||
}
|
||||
|
||||
export type UploadRequestMethod = 'POST' | 'PUT' | 'PATCH' | 'post' | 'put' | 'patch';
|
||||
|
||||
export type UploadRequestHeader = Record<string, string>;
|
||||
|
||||
export interface UploadRequestError extends Error {
|
||||
status?: number;
|
||||
method?: UploadRequestMethod;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface UploadRequestOption<T = any> {
|
||||
onProgress?: (event: UploadProgressEvent) => void;
|
||||
onError?: (event: UploadRequestError | ProgressEvent, body?: T) => void;
|
||||
onSuccess?: (body: T, xhr?: XMLHttpRequest) => void;
|
||||
data?: Record<string, unknown>;
|
||||
filename?: string;
|
||||
file: Exclude<BeforeUploadFileType, File | boolean> | RcFile;
|
||||
withCredentials?: boolean;
|
||||
action: string;
|
||||
headers?: UploadRequestHeader;
|
||||
method: UploadRequestMethod;
|
||||
}
|
||||
|
||||
export interface RcFile extends File {
|
||||
uid: string;
|
||||
}
|
@ -1,13 +1,15 @@
|
||||
function getError(option, xhr) {
|
||||
import type { UploadRequestOption, UploadRequestError, UploadProgressEvent } from './interface';
|
||||
|
||||
function getError(option: UploadRequestOption, xhr: XMLHttpRequest) {
|
||||
const msg = `cannot ${option.method} ${option.action} ${xhr.status}'`;
|
||||
const err = new Error(msg);
|
||||
const err = new Error(msg) as UploadRequestError;
|
||||
err.status = xhr.status;
|
||||
err.method = option.method;
|
||||
err.url = option.action;
|
||||
return err;
|
||||
}
|
||||
|
||||
function getBody(xhr) {
|
||||
function getBody(xhr: XMLHttpRequest) {
|
||||
const text = xhr.responseText || xhr.response;
|
||||
if (!text) {
|
||||
return text;
|
||||
@ -20,22 +22,12 @@ function getBody(xhr) {
|
||||
}
|
||||
}
|
||||
|
||||
// option {
|
||||
// onProgress: (event: { percent: number }): void,
|
||||
// onError: (event: Error, body?: Object): void,
|
||||
// onSuccess: (body: Object): void,
|
||||
// data: Object,
|
||||
// filename: String,
|
||||
// file: File,
|
||||
// withCredentials: Boolean,
|
||||
// action: String,
|
||||
// headers: Object,
|
||||
// }
|
||||
export default function upload(option) {
|
||||
const xhr = new window.XMLHttpRequest();
|
||||
export default function upload(option: UploadRequestOption) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
if (option.onProgress && xhr.upload) {
|
||||
xhr.upload.onprogress = function progress(e) {
|
||||
xhr.upload.onprogress = function progress(e: UploadProgressEvent) {
|
||||
if (e.total > 0) {
|
||||
e.percent = (e.loaded / e.total) * 100;
|
||||
}
|
||||
@ -43,7 +35,8 @@ export default function upload(option) {
|
||||
};
|
||||
}
|
||||
|
||||
const formData = new window.FormData();
|
||||
// eslint-disable-next-line no-undef
|
||||
const formData = new FormData();
|
||||
|
||||
if (option.data) {
|
||||
Object.keys(option.data).forEach(key => {
|
||||
@ -58,11 +51,16 @@ export default function upload(option) {
|
||||
return;
|
||||
}
|
||||
|
||||
formData.append(key, option.data[key]);
|
||||
formData.append(key, value as string | Blob);
|
||||
});
|
||||
}
|
||||
|
||||
formData.append(option.filename, option.file);
|
||||
// eslint-disable-next-line no-undef
|
||||
if (option.file instanceof Blob) {
|
||||
formData.append(option.filename, option.file, (option.file as any).name);
|
||||
} else {
|
||||
formData.append(option.filename, option.file);
|
||||
}
|
||||
|
||||
xhr.onerror = function error(e) {
|
||||
option.onError(e);
|
||||
@ -75,7 +73,7 @@ export default function upload(option) {
|
||||
return option.onError(getError(option, xhr), getBody(xhr));
|
||||
}
|
||||
|
||||
option.onSuccess(getBody(xhr), xhr);
|
||||
return option.onSuccess(getBody(xhr), xhr);
|
||||
};
|
||||
|
||||
xhr.open(option.method, option.action, true);
|
||||
@ -93,11 +91,12 @@ export default function upload(option) {
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
}
|
||||
|
||||
for (const h in headers) {
|
||||
if (headers.hasOwnProperty(h) && headers[h] !== null) {
|
||||
Object.keys(headers).forEach(h => {
|
||||
if (headers[h] !== null) {
|
||||
xhr.setRequestHeader(h, headers[h]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
xhr.send(formData);
|
||||
|
||||
return {
|
@ -1,262 +0,0 @@
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import partition from 'lodash-es/partition';
|
||||
import classNames from '../../_util/classNames';
|
||||
import defaultRequest from './request';
|
||||
import getUid from './uid';
|
||||
import attrAccept from './attr-accept';
|
||||
import traverseFileTree from './traverseFileTree';
|
||||
import { getSlot } from '../../_util/props-util';
|
||||
|
||||
const upLoadPropTypes = {
|
||||
componentTag: PropTypes.string,
|
||||
// style: PropTypes.object,
|
||||
prefixCls: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
// className: PropTypes.string,
|
||||
multiple: PropTypes.looseBool,
|
||||
directory: PropTypes.looseBool,
|
||||
disabled: PropTypes.looseBool,
|
||||
accept: PropTypes.string,
|
||||
// children: PropTypes.any,
|
||||
// onStart: PropTypes.func,
|
||||
data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
action: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
headers: PropTypes.object,
|
||||
beforeUpload: PropTypes.func,
|
||||
customRequest: PropTypes.func,
|
||||
// onProgress: PropTypes.func,
|
||||
withCredentials: PropTypes.looseBool,
|
||||
openFileDialogOnClick: PropTypes.looseBool,
|
||||
transformFile: PropTypes.func,
|
||||
method: PropTypes.string,
|
||||
};
|
||||
|
||||
const AjaxUploader = {
|
||||
inheritAttrs: false,
|
||||
name: 'ajaxUploader',
|
||||
mixins: [BaseMixin],
|
||||
props: upLoadPropTypes,
|
||||
data() {
|
||||
this.reqs = {};
|
||||
return {
|
||||
uid: getUid(),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this._isMounted = true;
|
||||
},
|
||||
beforeUnmount() {
|
||||
this._isMounted = false;
|
||||
this.abort();
|
||||
},
|
||||
methods: {
|
||||
onChange(e) {
|
||||
const files = e.target.files;
|
||||
this.uploadFiles(files);
|
||||
this.reset();
|
||||
},
|
||||
onClick() {
|
||||
const el = this.$refs.fileInputRef;
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
el.click();
|
||||
},
|
||||
onKeyDown(e) {
|
||||
if (e.key === 'Enter') {
|
||||
this.onClick();
|
||||
}
|
||||
},
|
||||
onFileDrop(e) {
|
||||
const { multiple } = this.$props;
|
||||
e.preventDefault();
|
||||
if (e.type === 'dragover') {
|
||||
return;
|
||||
}
|
||||
if (this.directory) {
|
||||
traverseFileTree(e.dataTransfer.items, this.uploadFiles, _file =>
|
||||
attrAccept(_file, this.accept),
|
||||
);
|
||||
} else {
|
||||
let files = partition(Array.prototype.slice.call(e.dataTransfer.files), file =>
|
||||
attrAccept(file, this.accept),
|
||||
);
|
||||
let successFiles = files[0];
|
||||
const errorFiles = files[1];
|
||||
if (multiple === false) {
|
||||
successFiles = successFiles.slice(0, 1);
|
||||
}
|
||||
this.uploadFiles(successFiles);
|
||||
|
||||
if (errorFiles.length) {
|
||||
this.__emit('reject', errorFiles);
|
||||
}
|
||||
}
|
||||
},
|
||||
uploadFiles(files) {
|
||||
const postFiles = Array.prototype.slice.call(files);
|
||||
postFiles
|
||||
.map(file => {
|
||||
file.uid = getUid();
|
||||
return file;
|
||||
})
|
||||
.forEach(file => {
|
||||
this.upload(file, postFiles);
|
||||
});
|
||||
},
|
||||
upload(file, fileList) {
|
||||
if (!this.beforeUpload) {
|
||||
// always async in case use react state to keep fileList
|
||||
return setTimeout(() => this.post(file), 0);
|
||||
}
|
||||
|
||||
const before = this.beforeUpload(file, fileList);
|
||||
if (before && before.then) {
|
||||
before
|
||||
.then(processedFile => {
|
||||
const processedFileType = Object.prototype.toString.call(processedFile);
|
||||
if (processedFileType === '[object File]' || processedFileType === '[object Blob]') {
|
||||
return this.post(processedFile);
|
||||
}
|
||||
return this.post(file);
|
||||
})
|
||||
.catch(e => {
|
||||
console && console.log(e); // eslint-disable-line
|
||||
});
|
||||
} else if (before !== false) {
|
||||
setTimeout(() => this.post(file), 0);
|
||||
}
|
||||
},
|
||||
post(file) {
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
const { $props: props } = this;
|
||||
let { data } = props;
|
||||
const { transformFile = originFile => originFile } = props;
|
||||
|
||||
new Promise(resolve => {
|
||||
const { action } = this;
|
||||
if (typeof action === 'function') {
|
||||
return resolve(action(file));
|
||||
}
|
||||
resolve(action);
|
||||
}).then(action => {
|
||||
const { uid } = file;
|
||||
const request = this.customRequest || defaultRequest;
|
||||
const transform = Promise.resolve(transformFile(file)).catch(e => {
|
||||
console.error(e); // eslint-disable-line no-console
|
||||
});
|
||||
transform.then(transformedFile => {
|
||||
if (typeof data === 'function') {
|
||||
data = data(file);
|
||||
}
|
||||
|
||||
const requestOption = {
|
||||
action,
|
||||
filename: this.name,
|
||||
data,
|
||||
file: transformedFile,
|
||||
headers: this.headers,
|
||||
withCredentials: this.withCredentials,
|
||||
method: props.method || 'post',
|
||||
onProgress: e => {
|
||||
this.__emit('progress', e, file);
|
||||
},
|
||||
onSuccess: (ret, xhr) => {
|
||||
delete this.reqs[uid];
|
||||
this.__emit('success', ret, file, xhr);
|
||||
},
|
||||
onError: (err, ret) => {
|
||||
delete this.reqs[uid];
|
||||
this.__emit('error', err, ret, file);
|
||||
},
|
||||
};
|
||||
this.reqs[uid] = request(requestOption);
|
||||
this.__emit('start', file);
|
||||
});
|
||||
});
|
||||
},
|
||||
reset() {
|
||||
this.setState({
|
||||
uid: getUid(),
|
||||
});
|
||||
},
|
||||
abort(file) {
|
||||
const { reqs } = this;
|
||||
if (file) {
|
||||
let uid = file;
|
||||
if (file && file.uid) {
|
||||
uid = file.uid;
|
||||
}
|
||||
if (reqs[uid] && reqs[uid].abort) {
|
||||
reqs[uid].abort();
|
||||
}
|
||||
delete reqs[uid];
|
||||
} else {
|
||||
Object.keys(reqs).forEach(uid => {
|
||||
if (reqs[uid] && reqs[uid].abort) {
|
||||
reqs[uid].abort();
|
||||
}
|
||||
|
||||
delete reqs[uid];
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const { $props, $attrs } = this;
|
||||
const {
|
||||
componentTag: Tag,
|
||||
prefixCls,
|
||||
disabled,
|
||||
multiple,
|
||||
accept,
|
||||
directory,
|
||||
openFileDialogOnClick,
|
||||
} = $props;
|
||||
const { class: className, style, id } = $attrs;
|
||||
const cls = classNames({
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
[className]: className,
|
||||
});
|
||||
const events = disabled
|
||||
? {}
|
||||
: {
|
||||
onClick: openFileDialogOnClick ? this.onClick : () => {},
|
||||
onKeydown: openFileDialogOnClick ? this.onKeyDown : () => {},
|
||||
onDrop: this.onFileDrop,
|
||||
onDragover: this.onFileDrop,
|
||||
};
|
||||
const tagProps = {
|
||||
...events,
|
||||
role: 'button',
|
||||
tabindex: disabled ? null : '0',
|
||||
class: cls,
|
||||
style,
|
||||
};
|
||||
return (
|
||||
<Tag {...tagProps}>
|
||||
<input
|
||||
id={id}
|
||||
type="file"
|
||||
ref="fileInputRef"
|
||||
onClick={e => e.stopPropagation()} // https://github.com/ant-design/ant-design/issues/19948
|
||||
key={this.uid}
|
||||
style={{ display: 'none' }}
|
||||
accept={accept}
|
||||
directory={directory ? 'directory' : null}
|
||||
webkitdirectory={directory ? 'webkitdirectory' : null}
|
||||
multiple={multiple}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
{getSlot(this)}
|
||||
</Tag>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default AjaxUploader;
|
@ -1,281 +0,0 @@
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import classNames from '../../_util/classNames';
|
||||
import getUid from './uid';
|
||||
import warning from '../../_util/warning';
|
||||
import { getSlot, findDOMNode } from '../../_util/props-util';
|
||||
|
||||
const IFRAME_STYLE = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
opacity: 0,
|
||||
filter: 'alpha(opacity=0)',
|
||||
left: 0,
|
||||
zIndex: 9999,
|
||||
};
|
||||
|
||||
// diferent from AjaxUpload, can only upload on at one time, serial seriously
|
||||
const IframeUploader = {
|
||||
name: 'IframeUploader',
|
||||
mixins: [BaseMixin],
|
||||
props: {
|
||||
componentTag: PropTypes.string,
|
||||
// style: PropTypes.object,
|
||||
disabled: PropTypes.looseBool,
|
||||
prefixCls: PropTypes.string,
|
||||
// className: PropTypes.string,
|
||||
accept: PropTypes.string,
|
||||
// onStart: PropTypes.func,
|
||||
multiple: PropTypes.looseBool,
|
||||
// children: PropTypes.any,
|
||||
data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
action: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
name: PropTypes.string,
|
||||
},
|
||||
data() {
|
||||
this.file = {};
|
||||
return {
|
||||
uploading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onLoad() {
|
||||
if (!this.uploading) {
|
||||
return;
|
||||
}
|
||||
const { file } = this;
|
||||
let response;
|
||||
try {
|
||||
const doc = this.getIframeDocument();
|
||||
const script = doc.getElementsByTagName('script')[0];
|
||||
if (script && script.parentNode === doc.body) {
|
||||
doc.body.removeChild(script);
|
||||
}
|
||||
response = doc.body.innerHTML;
|
||||
this.__emit('success', response, file);
|
||||
} catch (err) {
|
||||
warning(
|
||||
false,
|
||||
'cross domain error for Upload. Maybe server should return document.domain script. see Note from https://github.com/react-component/upload',
|
||||
);
|
||||
response = 'cross-domain';
|
||||
this.__emit('error', err, null, file);
|
||||
}
|
||||
this.endUpload();
|
||||
},
|
||||
onChange() {
|
||||
const target = this.getFormInputNode();
|
||||
// ie8/9 don't support FileList Object
|
||||
// http://stackoverflow.com/questions/12830058/ie8-input-type-file-get-files
|
||||
const file = (this.file = {
|
||||
uid: getUid(),
|
||||
name:
|
||||
target.value &&
|
||||
target.value.substring(target.value.lastIndexOf('\\') + 1, target.value.length),
|
||||
});
|
||||
this.startUpload();
|
||||
const { $props: props } = this;
|
||||
if (!props.beforeUpload) {
|
||||
return this.post(file);
|
||||
}
|
||||
const before = props.beforeUpload(file);
|
||||
if (before && before.then) {
|
||||
before.then(
|
||||
() => {
|
||||
this.post(file);
|
||||
},
|
||||
() => {
|
||||
this.endUpload();
|
||||
},
|
||||
);
|
||||
} else if (before !== false) {
|
||||
this.post(file);
|
||||
} else {
|
||||
this.endUpload();
|
||||
}
|
||||
},
|
||||
getIframeNode() {
|
||||
return this.$refs.iframeRef;
|
||||
},
|
||||
getIframeDocument() {
|
||||
return this.getIframeNode().contentDocument;
|
||||
},
|
||||
getFormNode() {
|
||||
return this.getIframeDocument().getElementById('form');
|
||||
},
|
||||
getFormInputNode() {
|
||||
return this.getIframeDocument().getElementById('input');
|
||||
},
|
||||
getFormDataNode() {
|
||||
return this.getIframeDocument().getElementById('data');
|
||||
},
|
||||
getFileForMultiple(file) {
|
||||
return this.multiple ? [file] : file;
|
||||
},
|
||||
getIframeHTML(domain) {
|
||||
let domainScript = '';
|
||||
let domainInput = '';
|
||||
if (domain) {
|
||||
const script = 'script';
|
||||
domainScript = `<${script}>document.domain="${domain}";</${script}>`;
|
||||
domainInput = `<input name="_documentDomain" value="${domain}" />`;
|
||||
}
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<style>
|
||||
body,html {padding:0;margin:0;border:0;overflow:hidden;}
|
||||
</style>
|
||||
${domainScript}
|
||||
</head>
|
||||
<body>
|
||||
<form method="post"
|
||||
encType="multipart/form-data"
|
||||
action="" id="form"
|
||||
style="display:block;height:9999px;position:relative;overflow:hidden;">
|
||||
<input id="input" type="file"
|
||||
name="${this.name}"
|
||||
style="position:absolute;top:0;right:0;height:9999px;font-size:9999px;cursor:pointer;"/>
|
||||
${domainInput}
|
||||
<span id="data"></span>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
},
|
||||
initIframeSrc() {
|
||||
if (this.domain) {
|
||||
this.getIframeNode().src = `javascript:void((function(){
|
||||
var d = document;
|
||||
d.open();
|
||||
d.domain='${this.domain}';
|
||||
d.write('');
|
||||
d.close();
|
||||
})())`;
|
||||
}
|
||||
},
|
||||
initIframe() {
|
||||
const iframeNode = this.getIframeNode();
|
||||
let win = iframeNode.contentWindow;
|
||||
let doc;
|
||||
this.domain = this.domain || '';
|
||||
this.initIframeSrc();
|
||||
try {
|
||||
doc = win.document;
|
||||
} catch (e) {
|
||||
this.domain = document.domain;
|
||||
this.initIframeSrc();
|
||||
win = iframeNode.contentWindow;
|
||||
doc = win.document;
|
||||
}
|
||||
doc.open('text/html', 'replace');
|
||||
doc.write(this.getIframeHTML(this.domain));
|
||||
doc.close();
|
||||
this.getFormInputNode().onchange = this.onChange;
|
||||
},
|
||||
endUpload() {
|
||||
if (this.uploading) {
|
||||
this.file = {};
|
||||
// hack avoid batch
|
||||
this.uploading = false;
|
||||
this.setState({
|
||||
uploading: false,
|
||||
});
|
||||
this.initIframe();
|
||||
}
|
||||
},
|
||||
startUpload() {
|
||||
if (!this.uploading) {
|
||||
this.uploading = true;
|
||||
this.setState({
|
||||
uploading: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
updateIframeWH() {
|
||||
const rootNode = findDOMNode(this);
|
||||
const iframeNode = this.getIframeNode();
|
||||
iframeNode.style.height = `${rootNode.offsetHeight}px`;
|
||||
iframeNode.style.width = `${rootNode.offsetWidth}px`;
|
||||
},
|
||||
abort(file) {
|
||||
if (file) {
|
||||
let uid = file;
|
||||
if (file && file.uid) {
|
||||
uid = file.uid;
|
||||
}
|
||||
if (uid === this.file.uid) {
|
||||
this.endUpload();
|
||||
}
|
||||
} else {
|
||||
this.endUpload();
|
||||
}
|
||||
},
|
||||
post(file) {
|
||||
const formNode = this.getFormNode();
|
||||
const dataSpan = this.getFormDataNode();
|
||||
let { data } = this.$props;
|
||||
if (typeof data === 'function') {
|
||||
data = data(file);
|
||||
}
|
||||
const inputs = document.createDocumentFragment();
|
||||
for (const key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('name', key);
|
||||
input.value = data[key];
|
||||
inputs.appendChild(input);
|
||||
}
|
||||
}
|
||||
dataSpan.appendChild(inputs);
|
||||
new Promise(resolve => {
|
||||
const { action } = this;
|
||||
if (typeof action === 'function') {
|
||||
return resolve(action(file));
|
||||
}
|
||||
resolve(action);
|
||||
}).then(action => {
|
||||
formNode.setAttribute('action', action);
|
||||
formNode.submit();
|
||||
dataSpan.innerHTML = '';
|
||||
this.__emit('start', file);
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.updateIframeWH();
|
||||
this.initIframe();
|
||||
});
|
||||
},
|
||||
updated() {
|
||||
this.$nextTick(() => {
|
||||
this.updateIframeWH();
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
const { componentTag: Tag, disabled, prefixCls } = this.$props;
|
||||
const { class: className, style } = this.$attrs;
|
||||
const iframeStyle = {
|
||||
...IFRAME_STYLE,
|
||||
display: this.uploading || disabled ? 'none' : '',
|
||||
};
|
||||
const cls = classNames({
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
[className]: className,
|
||||
});
|
||||
|
||||
return (
|
||||
<Tag class={cls} style={{ position: 'relative', zIndex: 0, ...style }}>
|
||||
<iframe ref="iframeRef" onLoad={this.onLoad} style={iframeStyle} />
|
||||
{getSlot(this)}
|
||||
</Tag>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default IframeUploader;
|
@ -1,97 +0,0 @@
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
import { initDefaultProps, getSlot } from '../../_util/props-util';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import AjaxUpload from './AjaxUploader';
|
||||
import IframeUpload from './IframeUploader';
|
||||
import { defineComponent, nextTick } from 'vue';
|
||||
|
||||
function empty() {}
|
||||
|
||||
const uploadProps = {
|
||||
componentTag: PropTypes.string,
|
||||
prefixCls: PropTypes.string,
|
||||
action: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
name: PropTypes.string,
|
||||
multipart: PropTypes.looseBool,
|
||||
directory: PropTypes.looseBool,
|
||||
onError: PropTypes.func,
|
||||
onSuccess: PropTypes.func,
|
||||
onProgress: PropTypes.func,
|
||||
onStart: PropTypes.func,
|
||||
data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
headers: PropTypes.object,
|
||||
accept: PropTypes.string,
|
||||
multiple: PropTypes.looseBool,
|
||||
disabled: PropTypes.looseBool,
|
||||
beforeUpload: PropTypes.func,
|
||||
customRequest: PropTypes.func,
|
||||
onReady: PropTypes.func,
|
||||
withCredentials: PropTypes.looseBool,
|
||||
supportServerRender: PropTypes.looseBool,
|
||||
openFileDialogOnClick: PropTypes.looseBool,
|
||||
method: PropTypes.string,
|
||||
};
|
||||
export default defineComponent({
|
||||
name: 'Upload',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
props: initDefaultProps(uploadProps, {
|
||||
componentTag: 'span',
|
||||
prefixCls: 'rc-upload',
|
||||
data: {},
|
||||
headers: {},
|
||||
name: 'file',
|
||||
multipart: false,
|
||||
onReady: empty,
|
||||
onStart: empty,
|
||||
onError: empty,
|
||||
onSuccess: empty,
|
||||
supportServerRender: false,
|
||||
multiple: false,
|
||||
beforeUpload: empty,
|
||||
withCredentials: false,
|
||||
openFileDialogOnClick: true,
|
||||
}),
|
||||
data() {
|
||||
this.Component = null;
|
||||
return {
|
||||
// Component: null, // 组件作为响应式数据,性能比较低,采用强制刷新
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
if (this.supportServerRender) {
|
||||
this.Component = this.getComponent();
|
||||
this.$forceUpdate();
|
||||
nextTick(() => {
|
||||
this.__emit('ready');
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
getComponent() {
|
||||
return typeof File !== 'undefined' ? AjaxUpload : IframeUpload;
|
||||
},
|
||||
abort(file) {
|
||||
this.$refs.uploaderRef.abort(file);
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const componentProps = {
|
||||
...this.$props,
|
||||
ref: 'uploaderRef',
|
||||
...this.$attrs,
|
||||
};
|
||||
if (this.supportServerRender) {
|
||||
const ComponentUploader = this.Component;
|
||||
if (ComponentUploader) {
|
||||
return <ComponentUploader {...componentProps}>{getSlot(this)}</ComponentUploader>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const ComponentUploader = this.getComponent();
|
||||
return <ComponentUploader {...componentProps}>{getSlot(this)}</ComponentUploader>;
|
||||
},
|
||||
});
|
@ -1,26 +0,0 @@
|
||||
function endsWith(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
export default (file, acceptedFiles) => {
|
||||
if (file && acceptedFiles) {
|
||||
const acceptedFilesArray = Array.isArray(acceptedFiles)
|
||||
? acceptedFiles
|
||||
: acceptedFiles.split(',');
|
||||
const fileName = file.name || '';
|
||||
const mimeType = file.type || '';
|
||||
const baseMimeType = mimeType.replace(/\/.*$/, '');
|
||||
|
||||
return acceptedFilesArray.some(type => {
|
||||
const validType = type.trim();
|
||||
if (validType.charAt(0) === '.') {
|
||||
return endsWith(fileName.toLowerCase(), validType.toLowerCase());
|
||||
} else if (/\/\*$/.test(validType)) {
|
||||
// This is something like a image/* mime type
|
||||
return baseMimeType === validType.replace(/\/.*$/, '');
|
||||
}
|
||||
return mimeType === validType;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
};
|
@ -1,4 +0,0 @@
|
||||
// export this package's api
|
||||
import Upload from './Upload';
|
||||
|
||||
export default Upload;
|
@ -1,9 +1,21 @@
|
||||
function loopFiles(item, callback) {
|
||||
import type { RcFile } from './interface';
|
||||
|
||||
interface InternalDataTransferItem extends DataTransferItem {
|
||||
isFile: boolean;
|
||||
file: (cd: (file: RcFile & { webkitRelativePath?: string }) => void) => void;
|
||||
createReader: () => any;
|
||||
fullPath: string;
|
||||
isDirectory: boolean;
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
function loopFiles(item: InternalDataTransferItem, callback) {
|
||||
const dirReader = item.createReader();
|
||||
let fileList = [];
|
||||
|
||||
function sequence() {
|
||||
dirReader.readEntries(entries => {
|
||||
dirReader.readEntries((entries: InternalDataTransferItem[]) => {
|
||||
const entryList = Array.prototype.slice.apply(entries);
|
||||
fileList = fileList.concat(entryList);
|
||||
|
||||
@ -21,9 +33,11 @@ function loopFiles(item, callback) {
|
||||
sequence();
|
||||
}
|
||||
|
||||
const traverseFileTree = (files, callback, isAccepted) => {
|
||||
const _traverseFileTree = (item, path) => {
|
||||
path = path || '';
|
||||
const traverseFileTree = (files: InternalDataTransferItem[], callback, isAccepted) => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const _traverseFileTree = (item: InternalDataTransferItem, path?: string) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
item.path = path || '';
|
||||
if (item.isFile) {
|
||||
item.file(file => {
|
||||
if (isAccepted(file)) {
|
||||
@ -34,7 +48,8 @@ const traverseFileTree = (files, callback, isAccepted) => {
|
||||
writable: true,
|
||||
},
|
||||
});
|
||||
file.webkitRelativePath = item.fullPath.replace(/^\//, '');
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
(file as any).webkitRelativePath = item.fullPath.replace(/^\//, '');
|
||||
Object.defineProperties(file, {
|
||||
webkitRelativePath: {
|
||||
writable: false,
|
||||
@ -45,16 +60,16 @@ const traverseFileTree = (files, callback, isAccepted) => {
|
||||
}
|
||||
});
|
||||
} else if (item.isDirectory) {
|
||||
loopFiles(item, entries => {
|
||||
loopFiles(item, (entries: InternalDataTransferItem[]) => {
|
||||
entries.forEach(entryItem => {
|
||||
_traverseFileTree(entryItem, `${path}${item.name}/`);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
for (const file of files) {
|
||||
_traverseFileTree(file.webkitGetAsEntry());
|
||||
}
|
||||
files.forEach(file => {
|
||||
_traverseFileTree(file.webkitGetAsEntry() as any);
|
||||
});
|
||||
};
|
||||
|
||||
export default traverseFileTree;
|
@ -2,5 +2,6 @@ const now = +new Date();
|
||||
let index = 0;
|
||||
|
||||
export default function uid() {
|
||||
// eslint-disable-next-line no-plusplus
|
||||
return `vc-upload-${now}-${++index}`;
|
||||
}
|
@ -222,7 +222,6 @@
|
||||
"vue-antd-md-loader": "^1.2.1-beta.1",
|
||||
"vue-clipboard2": "0.3.3",
|
||||
"vue-drag-resize": "^2.0.3",
|
||||
"vue-draggable-resizable": "^2.1.0",
|
||||
"vue-eslint-parser": "^8.0.0",
|
||||
"vue-i18n": "^9.1.7",
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
|
@ -1,5 +1,5 @@
|
||||
// debugger tsx
|
||||
import Demo from '../../components/form/demo/normal-login.vue';
|
||||
import Demo from '../../components/upload/demo/defaultFileList.vue';
|
||||
// import Demo from './demo/demo.vue';
|
||||
|
||||
export default {
|
||||
|
Loading…
Reference in New Issue
Block a user