上传 Upload
用户可传输文件或提交相应的内容。
基本使用
上传组件的基本用法。
代码事例
vue
<template>
<fk-space direction="vertical" :style="{ width: '100%' }">
<fk-upload action="/" />
<fk-upload action="/" disabled style="margin-top: 40px;"/>
</fk-space>
</template>用户头像上传
点击上传用户头像,可使用 beforeUpload 限制用户上传的图片格式和大小。
代码事例
vue
<template>
<fk-space direction="vertical" :style="{ width: '100%' }">
<fk-upload
action="/"
:file-list="file ? [file] : []"
:show-file-list="false"
@change="onChange"
@progress="onProgress"
>
<template #upload-button>
<div
:class="`fk-upload-list-item${
file && file.status === 'error' ? ' fk-upload-list-item-error' : ''
}`"
>
<div
v-if="file && file.url"
class="fk-upload-list-picture custom-upload-avatar"
>
<img :src="file.url" />
<div class="fk-upload-list-picture-mask">
<IconEdit />
</div>
<fk-progress
v-if="file.status === 'uploading' && file.percent < 100"
:percent="file.percent"
type="circle"
size="mini"
:style="{
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translateX(-50%) translateY(-50%)',
}"
/>
</div>
<div v-else class="fk-upload-picture-card">
<div class="fk-upload-picture-card-text">
<IconPlus />
<div style="margin-top: 10px; font-weight: 600">Upload</div>
</div>
</div>
</div>
</template>
</fk-upload>
</fk-space>
</template>
<script>
import { ref } from 'vue';
import { IconEdit, IconPlus } from '@erp/common';
export default {
components: {IconPlus, IconEdit},
setup() {
const file = ref();
const onChange = (_, currentFile) => {
file.value = {
...currentFile,
// url: URL.createObjectURL(currentFile.file),
};
};
const onProgress = (currentFile) => {
file.value = currentFile;
};
return {
file,
onChange,
onProgress
}
},
};
</script>已上传的文件列表
可以指定默认的已上传文件列表。
代码事例
vue
<template>
<fk-upload action="/" showLink imagePreview :default-file-list="fileList" />
</template>
<script>
export default {
setup() {
const fileList = [
{
uid: '-1',
name: 'ice.png',
url: '//test.img.fukerp.com/default/AQZ2oYAqJgZf2DjwAAzF0LRCiosB6kvkG6f0eKSL.jpg',
},
{
status: 'error',
uid: '-2',
percent: 0,
response: '上传错误提示',
name: 'cat.png',
url: '//test.img.fukerp.com/default/j44G9LTLBxBkNlLu84HOSGF6qgzQLjg7kK3WuuVg.jpg',
},
{
uid: '-3',
name: 'light.png',
url: '//test.img.fukerp.com/default/FLIrNHVfnvjvOXN40Rm1l5dugEwsjUDsxEDW3kIP.jpg',
},
];
return {
fileList
}
},
};
</script>照片墙
通过设置 list-type="picture-card" 开启照片墙模式。
代码事例
vue
<template>
<fk-upload
list-type="picture-card"
action="/"
:default-file-list="fileList"
image-preview
/>
</template>
<script>
export default {
setup() {
const fileList = [
{
uid: '-2',
name: '20200717-103937.png',
url: '//test.img.fukerp.com/default/FLIrNHVfnvjvOXN40Rm1l5dugEwsjUDsxEDW3kIP.jpg',
},
{
uid: '-1',
name: 'hahhahahahaha.png',
url: '//test.img.fukerp.com/default/j44G9LTLBxBkNlLu84HOSGF6qgzQLjg7kK3WuuVg.jpg',
},
];
return {
fileList
}
},
};
</script>拖拽上传
通过设置 draggable 开启对拖拽的支持。
代码事例
vue
<template>
<fk-upload draggable action="/" />
</template>图标列表样式
通过设置 list-type="picture" 开启图片列表样式
代码事例
vue
<template>
<fk-space direction="vertical" style="width: 100%">
<fk-upload
list-type="picture"
accept="*"
action="/"
image-preview
:default-file-list="fileList"
/>
<fk-upload
draggable
list-type="picture"
accept="*"
action="/"
image-preview
:default-file-list="fileList"
/>
</fk-space>
</template>
<script>
export default {
setup() {
const fileList = [
{
uid: '-2',
name: '20200717-103937.png',
url: '//test.img.fukerp.com/default/FLIrNHVfnvjvOXN40Rm1l5dugEwsjUDsxEDW3kIP.jpg',
},
{
uid: '-1',
name: 'hahhahahahaha.png',
url: '//test.img.fukerp.com/default/j44G9LTLBxBkNlLu84HOSGF6qgzQLjg7kK3WuuVg.jpg',
},
];
return {
fileList
}
},
};
</script>手动上传
设置 auto-upload 为 false 时候,可以通过调用 submit 方法进行手动上传。
代码事例
vue
<template>
<div>
<fk-upload
ref="uploadRef"
action="/"
:auto-upload="false"
multiple
@change="onChange"
>
<template #upload-button>
<fk-space>
<fk-button> select file</fk-button>
<fk-button type="primary" @click="submit"> start upload</fk-button>
<fk-button type="primary" @click="submitOne">
only upload one
</fk-button>
</fk-space>
</template>
</fk-upload>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const uploadRef = ref();
const files = ref([]);
const submitOne = (e) => {
e.stopPropagation();
console.log(files.value);
uploadRef.value.submit(files.value.find((x) => x.status === 'init'));
};
const submit = (e) => {
e.stopPropagation();
uploadRef.value.submit();
};
const onChange = (fileList) => {
files.value = fileList;
};
return {
uploadRef,
files,
submitOne,
submit,
onChange,
};
},
};
</script>上传前校验
beforeUpload 会在每一个文件上传之前执行。如果返回 false 或者 Promise.reject, 那么将会取消当前文件的上传。
代码事例
vue
<template>
<fk-space direction="vertical" :style="{ width: '100%' }">
<fk-upload action="/" @before-upload="beforeUpload" />
</fk-space>
</template>
<script>
import { Modal } from '@erp/common';
export default {
setup() {
const beforeUpload = (file) => {
return new Promise((resolve, reject) => {
Modal.confirm({
title: 'beforeUpload',
content: `确认上传 ${file.name}`,
onOk: () => resolve(true),
onCancel: () => reject('cancel'),
});
});
};
return {
beforeUpload
}
},
};
</script>移除前校验
on-before-remove 会在每一个文件移除之前执行。如果返回 false 或者 Promise.reject, 那么将会取消当前文件的操作。
代码事例
vue
<template>
<fk-space direction="vertical" :style="{ width: '100%' }">
<fk-upload
action="/"
:default-file-list="[
{
uid: '-2',
name: 'light.png',
url: '//test.img.fukerp.com/default/FLIrNHVfnvjvOXN40Rm1l5dugEwsjUDsxEDW3kIP.jpg',
},
{
uid: '-1',
name: 'ice.png',
url: '//test.img.fukerp.com/default/AQZ2oYAqJgZf2DjwAAzF0LRCiosB6kvkG6f0eKSL.jpg',
},
]"
@before-remove="beforeRemove"
/>
</fk-space>
</template>
<script>
import { Modal } from '@erp/common';
export default {
setup() {
const beforeRemove = (file) => {
return new Promise((resolve, reject) => {
Modal.confirm({
title: 'on-before-remove',
content: `确认删除 ${file.name}`,
onOk: () => resolve(true),
onCancel: () => reject('cancel'),
});
});
};
return {
beforeRemove
}
},
};
</script>限制上传数量
通过 limit 限制上传的最大数量。超出后上传按钮会隐藏.
代码事例
vue
<template>
<fk-upload multiple action="/" :limit="3" />
</template>自定义上传节点
可以通过插槽 upload-button 传入自定义内容作为文件上传的触发节点。
代码事例
vue
<template>
<fk-upload action="/">
<template #upload-button>
<div
style="
background-color: var(--color-fill-2);
color: var(--color-text-1);
border: 1px dashed var(--color-fill-4);
height: 158px;
width: 380px;
border-radius: 2;
line-height: 158px;
text-align: center;"
>
<div>
Drag the file here or
<span style="color: #3370FF"> Click to upload</span>
</div>
</div>
</template>
</fk-upload>
</template>自定义图标
自定义图标
代码事例
vue
<template>
<div>
<div style="margin-bottom: 20px;">
<fk-space>
<span>Type: </span>
<fk-radio-group v-model="type">
<fk-radio value="text">text</fk-radio>
<fk-radio value="picture">picture</fk-radio>
<fk-radio value="picture-card">picture-card</fk-radio>
</fk-radio-group>
</fk-space>
</div>
<fk-upload
action="/"
:list-type="type"
:default-file-list="[
{
uid: '-1',
name: 'ice.png',
url: '//test.img.fukerp.com/default/AQZ2oYAqJgZf2DjwAAzF0LRCiosB6kvkG6f0eKSL.jpg',
},
{
uid: '-3',
name: 'light.png',
url: '//test.img.fukerp.com/default/FLIrNHVfnvjvOXN40Rm1l5dugEwsjUDsxEDW3kIP.jpg',
},
]"
:custom-icon="getCustomIcon()"
/>
</div>
</template>
<script>
import { h, ref } from 'vue';
import { IconClose, IconFaceFrownFill, IconFileAudio, IconUpload } from '@erp/common';
export default {
setup() {
const type = ref('text');
const getCustomIcon = () => {
return {
retryIcon: () => h(IconUpload),
cancelIcon: () => h(IconClose),
fileIcon: () => h(IconFileAudio),
removeIcon: () => h(IconClose),
errorIcon: () => h(IconFaceFrownFill),
fileName: (file) => {
return `文件名: ${file.name}`
},
};
};
return {
type,
getCustomIcon
}
},
};
</script>自定义上传请求
可以通过 custom-request 实现自定义上传请求。
代码事例
vue
<template>
<fk-upload :custom-request="customRequest" />
</template>
<script>
export default {
setup() {
const customRequest = (option) => {
const {onProgress, onError, onSuccess, fileItem, name} = option
const xhr = new XMLHttpRequest();
if (xhr.upload) {
xhr.upload.onprogress = function (event) {
let percent;
if (event.total > 0) {
// 0 ~ 1
percent = event.loaded / event.total;
}
onProgress(percent, event);
};
}
xhr.onerror = function error(e) {
onError(e);
};
xhr.onload = function onload() {
if (xhr.status < 200 || xhr.status >= 300) {
return onError(xhr.responseText);
}
onSuccess(xhr.response);
};
const formData = new FormData();
formData.append(name || 'file', fileItem.file);
xhr.open('post', '//upload-z2.qbox.me/', true);
xhr.send(formData);
return {
abort() {
xhr.abort()
}
}
};
return {
customRequest
}
},
}
</script>文件夹上传
可以通过 directory 开启文件夹上传
代码事例
vue
<template>
<fk-space direction="vertical" :style="{ width: '100%' }">
<fk-upload action="/" directory />
</fk-space>
</template>API
<upload> Props
| 参数名 | 描述 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| file-list (v-model) | 文件列表 | FileItem[] | - | |
| default-file-list | 默认的文件列表(非受控状态) | FileItem[] | [] | |
| accept | 接收的上传文件类型,具体参考 HTML标准 | string | - | |
| action | 上传的URL | string | - | |
| disabled | 是否禁用 | boolean | false | |
| multiple | 是否支持多文件上传 | boolean | false | |
| directory | 是否支持文件夹上传(需要浏览器支持) | boolean | false | |
| draggable | 是否支持拖拽上传 | boolean | false | |
| drag-text | 拖拽提示文字 | string | - | |
| tip | 提示文字 | string | - | |
| tooltip | Hover 提示文字 | string | - | |
| headers | 上传请求附加的头信息 | Record<string, string> | - | |
| data | 上传请求附加的数据 | Record<string, string | Blob> | ((fileItem: FileItem) => Record<string, string | Blob>) | - | |
| name | 上传的文件名 | string | ((fileItem: FileItem) => string) | - | |
| with-credentials | 上传请求是否携带 cookie | boolean | false | |
| custom-request | 自定义上传行为 | (option: RequestOption) => UploadRequest | - | |
| limit | 限制上传文件的数量。0表示不限制 | number | 0 | |
| auto-upload | 是否自动上传文件 | boolean | true | |
| show-file-list | 是否显示文件列表 | boolean | true | |
| show-remove-button | 是否显示删除按钮 | boolean | true | 1.0.0 |
| show-retry-button | 是否显示重试按钮 | boolean | true | 1.0.0 |
| show-cancel-button | 是否显示取消按钮 | boolean | true | 1.0.0 |
| show-upload-button | 是否显示上传按钮。 | boolean | { showOnExceedLimit: boolean } | true | 1.0.0 |
| show-preview-button | 照片墙是否显示预览按钮 | boolean | true | 1.0.0 |
| show-picture-name | 是否显示图片名称 | boolean | true | |
| download | 是否在 <a> 链接上添加 download 属性 | boolean | false | 1.0.0 |
| show-link | 在列表模式下,如果上传的文件存在 URL 则展示链接。如果关闭仅展示文字并且点击可以触发 preview 事件。 | boolean | true | 1.0.0 |
| image-loading | <img> 的原生 HTML 属性,需要浏览器支持 | 'eager' | 'lazy' | - | 1.0.0 |
| list-type | 图片列表类型 | 'text' | 'picture' | 'picture-card' | 'text' | |
| response-url-key | Response中获取图片URL的key,开启后会用上传的图片替换预加载的图片 | string | ((fileItem: FileItem) => string) | - | |
| custom-icon | 自定义图标 | CustomIcon | - | |
| image-preview | 是否使用 ImagePreview 组件进行预览 | boolean | false | 1.0.0 |
| on-before-upload | 上传文件前触发 | (file: File) => boolean | Promise<boolean | File> | - | |
| on-after-upload | 上传文件后触发 | (file: FileItem) => void | - | |
| on-before-remove | 移除文件前触发 | (fileItem: FileItem) => Promise<boolean> | - | |
| on-button-click | 点击上传按钮触发(如果返回 Promise 则会关闭默认 input 上传) | (event: Event) => Promise<FileList> | void | - | |
| button-text | 上传按钮上展示的文字 | string | - | |
| pasted | 是否支持复制粘贴 | boolean | true |
<upload> Events
| 事件名 | 描述 | 参数 |
|---|---|---|
| exceed-limit | 上传的文件超出限制后触发 | fileList: FileItem[]files: File[] |
| change | 上传的文件状态发生改变时触发 | fileList: FileItem[]fileItem: fileItem |
| progress | 上传中的文件进度改变时触发 | fileItem: fileItemev: ProgressEvent |
| preview | 点击图片预览时的触发 | fileItem: FileItem |
| success | 上传成功时触发 | fileItem: FileItem |
| error | 上传失败时触发 | fileItem: FileItem |
<upload> Methods
| 方法名 | 描述 | 参数 | 返回值 | 版本 |
|---|---|---|---|---|
| submit | 上传文件(已经初始化完成的文件) | fileItem: FileItem | - | |
| abort | 中止上传 | fileItem: FileItem | - | |
| updateFile | 更新文件 | id: stringfile: File | - | |
| upload | 上传文件 | files: File[] | - | 1.0.0 |
<upload> Slots
| 插槽名 | 描述 | 参数 | 版本 |
|---|---|---|---|
| extra-button | 上传列表额外按钮 | fileItem: FileItem | 1.0.0 |
| image | 自定义图片 | fileItem: FileItem | 1.0.0 |
| file-name | 文件名称 | - | 1.0.0 |
| file-icon | 文件图标 | - | 1.0.0 |
| remove-icon | 删除图标 | - | 1.0.0 |
| preview-icon | 预览图标 | - | 1.0.0 |
| cancel-icon | 取消图标 | - | 1.0.0 |
| start-icon | 开始图标 | - | 1.0.0 |
| error-icon | 失败图标 | - | 1.0.0 |
| success-icon | 成功图标 | - | 1.0.0 |
| retry-icon | 重试图标 | - | 1.0.0 |
| upload-button | 上传按钮 | - | |
| upload-item | 上传列表的项目 | fileItem: FileItemindex: number |
FileItem
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| uid | 当前上传文件的唯一标示 | string | - |
| status | 当前上传文件的状态 | FileStatus | - |
| file | 文件对象 | File | - |
| percent | 上传进度百分比 | number | - |
| response | 当前文件上传请求返回的响应 | any | - |
| url | 文件地址 | string | - |
| name | 文件名 | string | - |
| id | 文件id | string | - |
CustomIcon
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| startIcon | 开始图标 | RenderFunction | - |
| cancelIcon | 取消图标 | RenderFunction | - |
| retryIcon | 重试图标 | RenderFunction | - |
| successIcon | 成功图标 | RenderFunction | - |
| errorIcon | 失败图标 | RenderFunction | - |
| removeIcon | 移除图标 | RenderFunction | - |
| previewIcon | 预览图标 | RenderFunction | - |
| fileIcon | 文件图标 | (fileItem: FileItem) => VNode | - |
| fileName | 文件名 | (fileItem: FileItem) => string | VNode | - |
RequestOption
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| action | 上传的URL | string | - |
| headers | 请求报文的头信息 | Record<string, string> | - |
| name | 上传文件的文件名 | string | ((fileItem: FileItem) => string) | - |
| fileItem | 上传文件 | FileItem | - |
| data | 附加的请求信息 | Record<string, string | Blob> | ((fileItem: FileItem) => Record<string, string | Blob>) | - |
| withCredentials | 是否携带cookie信息 | boolean | false |
| onProgress | 更新当前文件的上传进度。percent: 当前上传进度百分比 | (percent: number, event?: ProgressEvent) => void | - |
| onSuccess | 上传成功后,调用onSuccess方法,传入的response参数将会附加到当前上传文件的response字段上 | (response?: any) => void | - |
| onError | 上传失败后,调用onError方法,传入的response参数将会附加到当前上传文件的response字段上 | (response?: any) => void | - |
| async | 请求 | boolean | false |
UploadRequest
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| abort | 终止上传 | () => void | - |