目錄
一、文件上傳api?
二、封裝組件
三、使用案例
一、文件上傳api?
在src/api下新建file文件夾,并在file文件夾下新建index.ts和types.ts
// src/api/file/types.ts
/**
* 文件API類(lèi)型聲明
*/
export interface FileInfo {
name: string;
url: string;
}
// src/api/file/index.ts
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { FileInfo } from './types';
/**
* 上傳文件
*
* @param file
*/
export function uploadFileApi(file: File): AxiosPromise<FileInfo> {
const formData = new FormData();
formData.append('file', file);
return request({
url: '/api/v1/files',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
/**
* 刪除文件
*
* @param filePath 文件完整路徑
*/
export function deleteFileApi(filePath?: string) {
return request({
url: '/api/v1/files',
method: 'delete',
params: { filePath: filePath }
});
}
二、封裝組件
單文件上傳組件、多文件上傳組件
在src/components下新建Upload文件夾,并在Upload文件夾中新建SingleUpload.vue和MultiUpload.vue
<!--src/components/Upload/SingleUpload.vue-->
<template>
<!-- 上傳組件 -->
<el-upload
class="single-uploader"
v-model="imgUrl"
:show-file-list="false"
list-type="picture-card"
:before-upload="handleBeforeUpload"
:http-request="uploadFile"
>
<img v-if="imgUrl" :src="imgUrl" class="single" />
<el-icon v-else class="single-uploader-icon"><Plus /></el-icon>
</el-upload>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import {
ElMessage,
ElUpload,
UploadRawFile,
UploadRequestOptions
} from 'element-plus';
import { uploadFileApi } from '@/api/file';
const emit = defineEmits(['update:modelValue']);
const props = defineProps({
modelValue: {
type: String,
default: ''
}
});
const imgUrl = computed<string | undefined>({
get() {
return props.modelValue;
},
set(val) {
// imgUrl改變時(shí)觸發(fā)修改父組件綁定的v-model的值
emit('update:modelValue', val);
}
});
/**
* 自定義圖片上傳
*
* @param options
*/
async function uploadFile(options: UploadRequestOptions): Promise<any> {
const { data: fileInfo } = await uploadFileApi(options.file);
imgUrl.value = fileInfo.url;
}
/**
* 限制用戶(hù)上傳文件的格式和大小
*/
function handleBeforeUpload(file: UploadRawFile) {
if (file.size > 2 * 1048 * 1048) {
ElMessage.warning('上傳圖片不能大于2M');
return false;
}
return true;
}
</script>
<style scoped>
.single-uploader .single {
width: 178px;
height: 178px;
display: block;
}
</style>
<style>
.single-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.single-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.single-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>
<!--src/components/Upload/MultiUpload.vue-->
<!--
多圖上傳組件
@author: youlaitech
@date 2022/11/20
-->
<template>
<el-upload
v-model:file-list="fileList"
list-type="picture-card"
:before-upload="handleBeforeUpload"
:http-request="handleUpload"
:on-remove="handleRemove"
:on-preview="handlePreview"
:limit="props.limit"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import {
ElMessage,
ElUpload,
UploadRawFile,
UploadRequestOptions,
UploadUserFile,
UploadFile,
UploadProps
} from 'element-plus';
import { uploadFileApi, deleteFileApi } from '@/api/file';
const emit = defineEmits(['update:modelValue']);
const props = defineProps({
/**
* 文件路徑集合
*/
modelValue: {
type: Array<string>,
default: [] as Array<string>
},
/**
* 文件上傳數(shù)量限制
*/
limit: {
type: Number,
default: 5
}
});
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const fileList = ref([] as UploadUserFile[]);
watch(
() => props.modelValue,
(newVal: string[]) => {
const filePaths = fileList.value.map(file => file.url);
// 監(jiān)聽(tīng)modelValue文件集合值未變化時(shí),跳過(guò)賦值
if (
filePaths.length > 0 &&
filePaths.length === newVal.length &&
filePaths.every(x => newVal.some(y => y === x)) &&
newVal.every(y => filePaths.some(x => x === y))
) {
return;
}
fileList.value = newVal.map(filePath => {
return { url: filePath } as UploadUserFile;
});
},
{ immediate: true }
);
/**
* 自定義圖片上傳
*
* @param params
*/
async function handleUpload(options: UploadRequestOptions): Promise<any> {
// 上傳API調(diào)用
const { data: fileInfo } = await uploadFileApi(options.file);
// 上傳成功需手動(dòng)替換文件路徑為遠(yuǎn)程URL,否則圖片地址為預(yù)覽地址 blob:http://
const fileIndex = fileList.value.findIndex(
file => file.uid == (options.file as any).uid
);
fileList.value.splice(fileIndex, 1, {
name: fileInfo.name,
url: fileInfo.url
} as UploadUserFile);
emit(
'update:modelValue',
fileList.value.map(file => file.url)
);
}
/**
* 刪除圖片
*/
function handleRemove(removeFile: UploadFile) {
const filePath = removeFile.url;
if (filePath) {
deleteFileApi(filePath).then(() => {
// 刪除成功回調(diào)
emit(
'update:modelValue',
fileList.value.map(file => file.url)
);
});
}
}
/**
* 限制用戶(hù)上傳文件的格式和大小
*/
function handleBeforeUpload(file: UploadRawFile) {
if (file.size > 2 * 1048 * 1048) {
ElMessage.warning('上傳圖片不能大于2M');
return false;
}
return true;
}
/**
* 圖片預(yù)覽
*/
const handlePreview: UploadProps['onPreview'] = uploadFile => {
dialogImageUrl.value = uploadFile.url!;
dialogVisible.value = true;
};
</script>
三、使用案例
在src/views/component下新建uploader.vue
<!--src/views/component/uploader.vue-->
<script setup lang="ts">
import SingleUpload from '@/components/Upload/SingleUpload.vue';
import MultiUpload from '@/components/Upload/MultiUpload.vue';
import { ElForm } from 'element-plus';
import { reactive, ref, toRefs } from 'vue';
const dataFormRef = ref(ElForm);
const state = reactive({
formData: {
picUrl:
'https://oss.youlai.tech/default/2022/11/20/18e206dae97b40329661537d1e433639.jpg',
picUrls: [
'https://oss.youlai.tech/default/2022/11/20/8af5567816094545b53e76b38ae9c974.webp',
'https://oss.youlai.tech/default/2022/11/20/13dbfd7feaf848c2acec2b21675eb9d3.webp'
]
}
});
const { formData } = toRefs(state);
</script>
<template>
<div class="app-container">
<el-form ref="dataFormRef" :model="formData">
<el-form-item label="單圖上傳">
<single-upload v-model="formData.picUrl"></single-upload>
</el-form-item>
<el-form-item label="多圖上傳">
<multi-upload v-model="formData.picUrls"></multi-upload>
</el-form-item>
</el-form>
</div>
</template>
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-759040.html
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-759040.html
到了這里,關(guān)于Vue3后臺(tái)管理系統(tǒng)(十)文件上傳的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!