当前位置: 首页 > news >正文

UniApp基于xe-upload实现文件上传组件

xe-upload地址:文件选择、文件上传组件(图片,视频,文件等) - DCloud 插件市场

致敬开发者!!!

感觉好用的话,给xe-upload的作者一个好评

背景:开发中经常会有上传附件的情况,但是找了一圈没有满意的组件,无意间看到xe-upload,满足我需要上传图片和视频的需求,直接使用示例项目开始二次开发my-file-upload。

修改内容:

1.文件的点击事件

2.对video类型文件的处理

3.根据文件名称创建file文件内容

<template><view><view class="upload-wrap"><view class="cu-form-group1"><view class="label">{{label}}:</view><view class="btn-click mgb-16 upload-btn" @click="handleUploadClick" v-show="!disabled"><image :src="icons.upload" mode="aspectFill" class="upload-icon" /><text class="upload-text">上传{{ label }}</text></view></view><view class="mgb-16 file-wrap" v-for="(item, index) in fileList" :key="index"><view class="btn-click file-line" @click="handlePreview(item)"><!-- <view class="btn-click file-line" @click="handleUploadFile(item)"> --><view class="file-info"><image :src="icons[item.fileType || 'file']" mode="aspectFill" class="file-icon" /><text class="file-name">{{ item.name || title[type] }}</text></view><image :src="icons.close" mode="aspectFill" class="file-icon"@click.stop="handleDeleteFile(index)" /></view></view><view class="mgb-16 file-wrap" v-if="fileList.length === 0 && disabled"><view class="file-line"><text class="file-empty">暂无数据</text></view></view><view><video id="myVideo" :src="videoUrl" autoplay loop muted objectFit="cover" v-if="showVideo"></video></view></view><xe-upload ref="XeUpload" :options="uploadOptions" @callback="handleUploadCallback"></xe-upload></view>
</template><script>export default {name: 'MyFileUpload',components: {},props: {type: {default: 'image', // image, video, filetype: String,},list: {default: () => ([]),type: Array,},// disabled: {// 	default: false,// 	type: Boolean,// },value: {type: String, // 或者是 File[],取决于你的需求default: null},maxFile: {type: Number, //最大上传数量default: 1},label: {type: String, // 或者是 File[],取决于你的需求default: '附件'},},data() {return {// uploadOptions 参数跟uni.uploadFile的参数是一样的(除了类型为Function的属性)uploadOptions: {// url: 'http://192.168.31.185:3000/api/upload', // 不传入上传地址则返回本地链接},uploadUrl: "/sys/common/upload",staticUrl: "/sys/common/static/",fileList: [],title: {image: '图片',video: '视频',file: '文件',},icons: {upload: '/static/xeUpload/icon_upload.png',close: '/static/xeUpload/icon_close.png',image: '/static/xeUpload/icon_image.png',video: '/static/xeUpload/icon_video.png',file: '/static/xeUpload/icon_file.png',},disabled: false,showVideo: false,videoUrl: ''};},watch: {value: {async handler(val) {if (val && val !== null && val !== undefined) {const url = this.$config.apiUrl + this.staticUrl + val;const file = this.urlToFile(url);this.fileList = [file];if (this.fileList.length === this.maxFile) {this.disabled = true;}}},immediate: true,deep: true,},},onLoad: function() {this.videoContext = uni.createVideoContext('myVideo', this)},methods: {handleUploadClick() {// 使用默认配置则不需要传入第二个参数// App、H5 文件拓展名过滤 { extension: ['.doc', '.docx'] } 或者 { extension: '.doc, .docx' }this.$refs.XeUpload.upload(this.type);// 可以根据当前的平台,传入选择文件的参数,例如// 注意 当chooseMedia可用时,会优先使用chooseMedia// // uni.chooseImage// this.$refs.XeUpload.upload(type, {// 	count: 6,// 	sizeType: ['original', 'compressed'],// 	sourceType: ['album'],// });// // uni.chooseVideo// this.$refs.XeUpload.upload(type, {// 	sourceType: ['camera', 'album'],// });// // uni.chooseMedia (微信小程序2.10.0+;抖音小程序、飞书小程序;京东小程序支持)// this.$refs.XeUpload.upload(type, {// 	count: 9,// 	sourceType: ['album', 'camera'],// });},handleUploadCallback(e) {console.log('UploadCallback', e);if (['choose', 'success'].includes(e.type)) {// 根据接口返回修改对应的response相关的逻辑const tmpFiles = (e.data || []).map(({response,tempFilePath,name,fileType}) => {// 当前测试服务返回的数据结构如下// {//   "result": {//       "fileName": "fileName",//       "filePath": `http://192.168.1.121:3000/static/xxxxx.png`,//   },//   "success": true,// }const res = response?.result || {};const tmpUrl = res.filePath ?? tempFilePath;const tmpName = res.fileName ?? name;return {...res,url: tmpUrl,name: tmpName,fileType,};});this.fileList.push(...tmpFiles);this.handleUploadFile(e.data[0].tempFilePath);}},// 自定义上传handleUploadFile(url) {var that = this;console.log('UploadFile', url);if (url != undefined) {that.$http.upload(that.$config.apiUrl + that.uploadUrl + '?biz=temp', {filePath: url,name: 'file',}).then(res => {console.log('handleUpload success', res);//回传至表单that.$emit('input', res.data.message);const tmpData = JSON.parse(res.data);uni.showToast({title: tmpData.success ? '上传成功' : '上传失败',icon: 'none'});})}},// 预览handlePreview(item) {console.log('PreviewFile', item);const fileType = this.getFileType(item.name);const url = item.url;if (fileType === 'image') {return uni.previewImage({current: url,urls: [url],});}else if (fileType === 'video') {this.videoUrl = url;this.showVideo = !this.showVideo;//全屏显示// this.videoContext.requestFullScreen();}// #ifndef H5else if (fileType === 'office') {return uni.openDocument({filePath: url,fail: (err) => {console.log(err);uni.showToast({icon: 'none',title: '文件预览失败'});},});}// #endifelse{uni.showModal({title: '提示',content: url,showCancel: false,});}},handleDeleteFile(index) {this.fileList.splice(index, 1);if (this.fileList.length < this.maxFile) {this.disabled = false;}},urlToFile(url) {// 获取URL的最后一部分const lastPart = url.split('/').pop();// 获取文件名(不包括扩展名)const filenameWithoutExtension = lastPart.split('_').slice(0, -1).join('_');// 获取文件扩展名const extension = lastPart.split('.').pop();// 组合文件名和扩展名const filename = filenameWithoutExtension + '.' + extension;const fileType = this.getFileType(url);const file = {"fileName": filename,"fileKey": lastPart,"filePath": url,"url": url,"name": filename,"fileType": fileType}return file;},/*** 获取文件类型* @param {String} fileName 文件链接* @returns {String} fileType => '', image, video, audio, office, unknown*/getFileType(fileName = '') {const fileType = fileName.split('.').pop();// let suffix = flieArr[flieArr.length - 1];// if (!suffix) return '';// suffix = suffix.toLocaleLowerCase();const image = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp'];if (image.includes(fileType)) return 'image';const video = ['mp4', 'm4v'];if (video.includes(fileType)) return 'video';const audio = ['mp3', 'm4a', 'wav', 'aac'];if (audio.includes(fileType)) return 'audio';const office = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'plain'];if (office.includes(fileType)) return 'office';return 'unknown';},},};
</script><style lang="scss" scoped>view {box-sizing: border-box;}.label{text-align: justify;padding-right: 15px;white-space: nowrap;font-size: 15px;position: relative;height: 30px;line-height: 30px;}.cu-form-group1 {background-color: #ffffff;padding: 1px 15px 1px 0px;display: flex;align-items: center;min-height: 50px;// justify-content: space-between;}.btn-click {transition: all 0.3s;opacity: 1;}.btn-click:active {opacity: 0.5;}.mgb-16 {margin-bottom: 16rpx;&:last-child {margin-bottom: 0;}}.upload-wrap {width: 100%;border-radius: 16rpx;background: white;padding: 32rpx;.upload-btn {width: 60%;height: 120rpx;border: 2rpx dashed #AAAAAA;background: #FAFAFA;border-radius: 16rpx;display: flex;align-items: center;justify-content: center;flex-direction: column;.upload-icon {width: 48rpx;height: 48rpx;margin-bottom: 8rpx;}.upload-text {font-size: 26rpx;color: #9E9E9E;line-height: 40rpx;}}.file-wrap {.file-line {width: 100%;background: #F5F5F5;border-radius: 8rpx;padding: 16rpx;font-size: 26rpx;color: #1A1A1A;line-height: 40rpx;display: flex;align-items: center;justify-content: space-between;.file-info {width: 90%;display: flex;align-items: center;.file-name {max-width: 80%;padding-left: 16rpx;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}}.file-icon {width: 40rpx;height: 40rpx;flex-shrink: 0;}.file-empty {color: #999999;}}}}
</style>

父组件中引入使用

<my-file-upload type="file" v-model="model.attachment" label="附件"></my-file-upload>import myFileUpload from '@/components/my-componets/my-file-upload.vue';export default {name: "Test",components:{ myFileUpload },props:{formData:{type:Object,default:()=>{},required:false}},data(){return {model: {},}},onLoad: function (option) {}},created(){},methods:{}}


http://www.mrgr.cn/news/36778.html

相关文章:

  • Vue中input框自动聚焦
  • 餐厅包厢预订小程序
  • 第十二章RAS extension support
  • FineReport多数据源报表
  • 聊一聊软件测试的基本原则有哪些
  • 自闭症摘帽学校评价:家长共同推崇的信赖之选
  • Jenkins的安装
  • 王霞培优100分(全套)
  • 点击IDEA中的maven插件中的生命周期的命令发现没有效果,没有任何反应,解决办法在下面
  • C++ 基于 Epoll 的多客户端聊天室项目
  • GUET-CTF2019]soul sipse
  • k8s 1.28.2 集群部署 ingress 1.11.1 包含 admission-webhook
  • video视频标签播放视频时点击或拖拽进度条事件
  • 跨网文件交换是什么?FileLink跨网文件交换解决方案
  • ide使用技巧与插件推荐
  • netty编程之对3种IO模式的支持以及对应的关键源码分析
  • yolov5/v7/v8随机种子固定方法
  • 电脑usb接口封禁如何实现?5种禁用USB接口的方法分享!(第一种你GET了吗?)
  • 【已解决】Ubuntu 24.04 修改 ssh 连接端口无效
  • BSIM4 and MOSFET Modeling For IC Simulation