feat: 文件列表上传组件

This commit is contained in:
2023-08-16 18:25:21 +08:00
parent a241be7b00
commit 777bafbb7d
3 changed files with 119 additions and 0 deletions

View File

@ -0,0 +1,71 @@
<!--
* @Author: zhaojinfeng 121016171@qq.com
* @Date: 2023-08-16 17:33:41
* @LastEditors: zhaojinfeng 121016171@qq.com
* @LastEditTime: 2023-08-16 18:23:17
* @FilePath: \vue3\packages\upload-list\index.vue
* @Description:
*
-->
<template>
<el-upload v-model:file-list="value" :accept="accept" :http-request="httpRequest">
<el-button type="primary" plain>
点击上传
</el-button>
</el-upload>
</template>
<script lang="ts" setup name="ThUploadList">
import type { UploadRequestOptions, UploadUserFile } from 'element-plus'
const props = withDefaults(
defineProps<{
/** 可上传的文件类型 */
accept?: string
/** 文件集合 */
fileList?: FileVO[]
/** 文件上传的请求函数 */
request: (formData: FormData, args?: any) => Promise<FileVO>
/** 自定义文件上传路径前缀 */
filePath?: string
}>(), {
fileList: () => [],
},
)
const emit = defineEmits<{
(event: 'update:fileList', file: FileVO[]): void
}>()
let value = $ref<UploadUserFile[]>([])
async function httpRequest({ file, onProgress, onSuccess, onError }: UploadRequestOptions) {
const formData = new FormData()
formData.append('file', file)
if (props.filePath)
formData.append('filePath', props.filePath)
try {
const res = await props.request(formData, {
onUploadProgress: onProgress,
})
onSuccess(res)
emit('update:fileList', [...props.fileList, res])
}
catch (err) {
onError(err)
}
}
function init() {
if (value.length === 0) {
value = props.fileList.map(file => ({
name: file.name!,
url: file.url,
status: 'success',
}))
}
}
init()
watch(() => props.fileList, init)
</script>

View File

@ -0,0 +1,46 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import ThUploadList from '../packages/upload-list/index.vue'
import avatar from './assets/avatar.jpeg'
// 模拟2秒钟的接口请求
function request(formData: FormData) {
let name = '佚名文件'
let url = avatar
const fileName = formData.get('name')
const file = formData.get('file')
if (typeof fileName === 'string') {
name = fileName
}
else if (typeof file !== 'string' && file) {
name = file.name
url = URL.createObjectURL(file)
}
return new Promise<FileVO>((resolve) => {
setTimeout(() => {
resolve({
id: Date.now(),
name,
url,
createdBy: 'user',
})
}, 2000)
})
}
const meta = {
title: '表单组件/UploadList',
component: ThUploadList,
args: {
accept: '*',
fileList: [],
request,
filePath: '/',
},
tags: ['autodocs'],
} satisfies Meta<typeof ThUploadList>
export default meta
type Story = StoryObj<typeof meta>
export const Base: Story = {
name: '基本使用',
}

View File

@ -28,6 +28,7 @@ declare module 'vue' {
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTransfer: typeof import('element-plus/es')['ElTransfer']
ElUpload: typeof import('element-plus/es')['ElUpload']
Header: typeof import('./../packages/header/index.vue')['default']
MaskText: typeof import('./../packages/mask-text/index.vue')['default']
PreviewOffice: typeof import('./../packages/preview-office/index.vue')['default']
@ -37,6 +38,7 @@ declare module 'vue' {
SelectTableModal: typeof import('./../packages/select-table-modal/index.vue')['default']
SelectTransferModal: typeof import('./../packages/select-transfer-modal/index.vue')['default']
UploadAvatar: typeof import('./../packages/upload-avatar/index.vue')['default']
UploadList: typeof import('./../packages/upload-list/index.vue')['default']
UploadSingleFile: typeof import('./../packages/upload-single-file/index.vue')['default']
UploadTable: typeof import('./../packages/upload-table/index.vue')['default']
}