1. 前言
接手得 uniapp 開發的微信小程序項目,新的開發需求是需要同時上傳圖片和視頻,但是之前的上傳都沒有進行封裝,都是每個頁面需要的時候單獨實現,現在新的需求,有多個地方都需要上傳圖片、視頻或語音等,這樣就需要封裝一個組件,然后發現部分地方使用了 uni-file-picker 組件,但是 uni-file-picker 在 grid 的時候只能進行圖片的展示,如果是 video 或者 all 的時候,就會直接列表展示的文件名列表,不滿足我當前的需求,因此在 uni-file-picker 基礎上進行再次適配當前需求的封裝。
2. 實現效果
3. 分析
- 圖片和視頻同時預覽展示,就需要判斷上傳的是否是視頻或者圖片;
- 根據接口判斷是否上傳文件的格式是否在允許范圍內;
- 使用 uni-file-picker 需要改造,將文件預覽列表隱藏,使用自定義的預覽文件。
4. 判斷是圖片
export const isImageFile = (filename) => {// 定義常見的圖片文件擴展名const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']// 獲取文件擴展名const fileExtension = filename.split('.').pop().toLowerCase()// 判斷文件擴展名是否在圖片擴展名列表中return imageExtensions.includes(fileExtension)
}
5. 判斷是視頻
// 判斷是不是視頻
export const isVideoFile = (filename) => {// 定義常見的視頻文件擴展名const videoExtensions = ['mp4','avi','mov','mkv','flv','wmv','webm','mpeg','mpg']// 獲取文件擴展名const fileExtension = filename.split('.').pop().toLowerCase()// 判斷文件擴展名是否在視頻擴展名列表中return videoExtensions.includes(fileExtension)
}
6. 根據接口判斷是否是可上傳格式文件
export const canUploadFile = (filename) => {const extensions = ['bmp','gif','jpg','jpe','png','mp4','mp3']// 獲取文件擴展名const fileExtension = filename.split('.').pop().toLowerCase()// 判斷文件擴展名是否在視頻擴展名列表中return extensions.includes(fileExtension)
}
7. 預覽圖片和視頻
uploadPreview 插槽是方便自定義預覽,這里我是用 tailwindcss 實現了一個默認的視頻和圖片的預覽樣式。
<slot name="uploadPreview"><view class="cc mr-[20rpx] wh-[160] bd-[8] flex-none relative" v-for="(item,index) in fileLists" :key="item.url"><view class="icon-del-box" @click.stop="deletePic(item)"><view class="icon-del"></view><view class="icon-del rotate"></view></view><image v-if="item.isImage" :src="item.url" class="wh-[160] bd-[8] flex-none"></image><video v-else-if="item.isVideo" :src="item.url" class="wh-[160] bd-[8] flex-none"></video></view>
</slot>
8. 使用 uni-file-picker 上傳
- 注意:是對 list 模式的文件上傳,所以直接將 mode 的值寫死 list;
- uploadButtom 自定義上傳樣式。
<uni-file-picker:limit="limit":file-mediatype="fileMediatype"@select="getUpload":is-upload-file="false":autoUpload="false"mode="list":value="fileLists"
><slot name="uploadButtom"><viewclass="cc bg-[#F9F9F9] wh-[160] bd-[8] b-[2rpx_#D0D0D0_dashed] flex-none"><image :src="$icon.publishAddIcon" class="wh-[48]"></image></view></slot>
</uni-file-picker>
9. 完整組件實現
<template><view class="ac"><slot name="uploadPreview"><view class="cc mr-[20rpx] wh-[160] bd-[8] flex-none relative" v-for="(item,index) in fileLists" :key="item.url"><view class="icon-del-box" @click.stop="deletePic(item)"><view class="icon-del"></view><view class="icon-del rotate"></view></view><image v-if="item.isImage" :src="item.url" class="wh-[160] bd-[8