vue3移动端可同时上传照片和视频的组件
uni-app中的uni-file-picker可单独上传照片或视频,但不支持同时上传照片和视频。本篇博客使用image标签和video标签实现移动端(H5+app+小程序)中照片和视频的同时上传。
本篇博客采用的是照片和视频的单独上传,但可同时展示,支持照片和视频的删除,其中照片和视频均是调用的后端的接口,上传至服务器中,大家可根据个人需要灵活存储照片和视频。
实现效果:
实现代码 :
将照片和视频区分上传,并单独处理,照片采用image标签,视频采用video标签。
<template><!-- 上传视频或者图片 --><view class="up-page"><!--图片--><view class="show-box" v-for="(item, index) in imageList" :key="index"><imageclass="full":src="item":data-src="image"@tap="previewImage(item)"></image><view class="delect-icon" @tap="delect(index)"><image class="full" :src="clearIcon" mode=""></image></view></view><!--视频--><view class="show-box" v-for="(item1, index1) in videoList" :key="index1"><video class="full" :src="item1"></video><view class="delect-icon" @tap="delectVideo(index1)"><image class="full" :src="clearIcon" mode=""></image></view></view><view v-if="VideoOfImagesShow" @tap="chooseVideoImage" class="box-mode"><image class="full" :src="selectfile" mode=""></image></view></view>
</template>
对照片和视频分别进行上传、删除等操作,避免index值出现错乱,出现错删和误删。
配置项可进行父组件的传值灵活设置。
此处处理的是将后端上传后的照片或视频id传递出去,此处可根据个人需求灵活设置。但需注意的是,imageList和videoList不要轻易改变,此处是专门使用了对应的id数组进行了重新定义。
<script setup>
import { uploadImg, uploadVideo } from '@/api/upload'const emit = defineEmits(['getImgUploadIds', 'getVideoUploadIds'])var sourceType = [['camera'], ['album'], ['camera', 'album']]const clearIcon = ref('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCAwaDE2YTQgNCAwIDAgMSA0IDR2MTZINGE0IDQgMCAwIDEtNC00VjB6IiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXIpIiBmaWxsLW9wYWNpdHk9Ii45OCIgZmlsdGVyPSJ1cmwoI2ZpbHRlcjBfYikiLz48cGF0aCBkPSJNMTAuOTQgOS45OTlsMi44NjMtMi44NTdhLjY2OS42NjkgMCAxIDAtLjk0Ni0uOTQ2TDEwIDkuMDYgNy4xNDMgNi4xOTZhLjY2OS42NjkgMCAwIDAtLjk0Ni45NDZsMi44NjQgMi44NTctMi44NjQgMi44NTdhLjY2Ni42NjYgMCAwIDAgLjIxNyAxLjA5Mi42NjQuNjY0IDAgMCAwIC43MjktLjE0NkwxMCAxMC45MzhsMi44NTcgMi44NjRhLjY2Ny42NjcgMCAwIDAgMS4wOTItLjIxNy42NjYuNjY2IDAgMCAwLS4xNDYtLjcyOUwxMC45MzkgMTB6IiBmaWxsPSIjZmZmIi8+PGRlZnM+PGZpbHRlciBpZD0iZmlsdGVyMF9iIiB4PSItNCIgeT0iLTQiIHdpZHRoPSIyOCIgaGVpZ2h0PSIyOCIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPjxmZUZsb29kIGZsb29kLW9wYWNpdHk9IjAiIHJlc3VsdD0iQmFja2dyb3VuZEltYWdlRml4Ii8+PGZlR2F1c3NpYW5CbHVyIGluPSJCYWNrZ3JvdW5kSW1hZ2UiIHN0ZERldmlhdGlvbj0iMiIvPjxmZUNvbXBvc2l0ZSBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0iaW4iIHJlc3VsdD0iZWZmZWN0MV9iYWNrZ3JvdW5kQmx1ciIvPjxmZUJsZW5kIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfYmFja2dyb3VuZEJsdXIiIHJlc3VsdD0ic2hhcGUiLz48L2ZpbHRlcj48bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXIiIHgxPSIyMCIgeDI9IjE1LjU4NiIgeTI9IjIyLjk0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzBEMUUyOCIgc3RvcC1vcGFjaXR5PSIuOCIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA1MEUxMiIgc3RvcC1vcGFjaXR5PSIuNjUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4='
)
const selectfile = ref('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSIuMjUiIHk9Ii4yNSIgd2lkdGg9IjYzLjUiIGhlaWdodD0iNjMuNSIgcng9IjMuNzUiIGZpbGw9IiNGMkYyRjIiIHN0cm9rZT0iI0YyRjJGMiIgc3Ryb2tlLXdpZHRoPSIuNSIvPjxyZWN0IHg9IjE2IiB5PSIzMSIgd2lkdGg9IjMyIiBoZWlnaHQ9IjIiIHJ4PSIxIiBmaWxsPSIjQkZCRkJGIi8+PHJlY3QgeD0iMzMiIHk9IjE2IiB3aWR0aD0iMzIiIGhlaWdodD0iMiIgcng9IjEiIHRyYW5zZm9ybT0icm90YXRlKDkwIDMzIDE2KSIgZmlsbD0iI0JGQkZCRiIvPjwvc3ZnPg=='
)
const VideoOfImagesShow = ref(true) // 页面图片或视频数量超出后,拍照按钮隐藏
const imageList = ref([]) //存放图片的地址
const imageListIds = ref([]) //存放图片id的地址
const videoList = ref([]) //视频存放的地址
const videoListIds = ref([]) //存放视频id的地址
// const sourceType = ref(['拍摄', '相册', '拍摄或相册'])
const sourceTypeIndex = ref(2)
const cameraList = ref([{value: 'back',name: '后置摄像头',checked: 'true'},{value: 'front',name: '前置摄像头'}
])
const cameraIndex = ref(0) // 上传视频时的数量
const props = defineProps({// 上传配置项uploadConfig: {type: Object,required: true,default: () => {return {// maxCount: 3,// exParam: 'imgArr'}}},imgUrlStr: {type: [String, Array],required: true,default: () => {return []}}
})
// onUnload((val) => {
// ;(imageList.value = []),
// (sourceTypeIndex.value = 2),
// (sourceType.value = ['拍摄', '相册', '拍摄或相册'])
// }),
// 点击上传图片或视频
function chooseVideoImage() {uni.showActionSheet({title: '选择上传类型',itemList: ['图片', '视频'],success: (res) => {if (res.tapIndex == 0) {chooseImages()} else {chooseVideo()}}})
}
//上传图片
function chooseImages() {uni.chooseImage({count: props.uploadConfig.maxCount, // 允许选择的数量sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有sourceType: ['album', 'camera'], // 从相册选择success: (e) => {uni.showLoading({mask: true,title: '上传中,请稍侯'})uploadImg(e, props.uploadConfig.exParam).then((res) => {const ids = getImgUrl(res)imageListIds.value.push(ids)emit('getImgUploadIds', imageListIds.value)imageList.value = imageList.value.concat(e.tempFilePaths)uni.hideLoading()})if (imageList.value.length + videoList.value.length ==props.uploadConfig.maxCount) {VideoOfImagesShow.value = false //图片上传数量和count一样时,让点击拍照按钮消失}}})
}
//上传视频
function chooseVideo(index) {uni.chooseVideo({maxDuration: 60, //拍摄视频最长拍摄时间,单位秒。最长支持 60 秒count: props.uploadConfig.maxCount,camera: cameraList.value[cameraIndex.value].value, //'front'、'back',默认'back'sourceType: sourceType[sourceTypeIndex.value],success: (e) => {uni.showLoading({mask: true,title: '上传中,请稍侯'})uploadVideo(e, props.uploadConfig.exParam).then((res) => {const ids = getImgUrl(res)videoListIds.value.push(ids)emit('getVideoUploadIds', videoListIds.value)videoList.value = videoList.value.concat(e.tempFilePath)uni.hideLoading()})if (imageList.value.length + videoList.value.length ==props.uploadConfig.maxCount) {VideoOfImagesShow.value = false}}})
}
//预览图片
function previewImage(e) {uni.previewImage({current: e,urls: imageList.value})
}
// 删除图片
function delect(index) {uni.showModal({title: '提示',content: '是否要删除该图片',success: (res) => {if (res.confirm) {imageList.value.splice(index, 1)imageListIds.value.splice(index, 1)emit('getImgUploadIds', imageListIds.value)}if (imageList.value.length + videoList.value.length ==props.uploadConfig.maxCount) {VideoOfImagesShow.value = false} else {VideoOfImagesShow.value = true}}})
}
// 删除视频
function delectVideo(index) {uni.showModal({title: '提示',content: '是否要删除此视频',success: (res) => {if (res.confirm) {videoList.value.splice(index, 1)videoListIds.value.splice(index, 1)emit('getVideoUploadIds', videoListIds.value)}if (imageList.value.length + videoList.value.length ==props.uploadConfig.maxCount) {VideoOfImagesShow.value = false} else {VideoOfImagesShow.value = true}}})
}
// 处理图片
function getImgUrl(arr) {const idArr = []let idStr = ''arr.forEach((item) => {idArr.push(item.data.id)})idStr = idArr.join(',')return idStr
}
</script>
对视频和照片的尺寸进行定义。可灵活根据个人需求进行设置。
<style lang="scss">
/* 统一上传后显示的盒子宽高比 */
.box-mode {width: 20vw;height: 20vw;border-radius: 8rpx;overflow: hidden;
}.full {width: 100%;height: 100%;
}.up-page {display: flex;flex-wrap: wrap;display: flex;width: 100%;.show-box:nth-child(3n) {margin-right: 0;}.show-box {position: relative;margin-bottom: 4vw;margin-right: 4vw;@extend .box-mode;.delect-icon {height: 40rpx;width: 40rpx;position: absolute;right: 0rpx;top: 0rpx;z-index: 1000;}}
}
</style>
以上三部分可组合为一个完整的vue组件,可在父组件中使用。父组件的使用实例
<FileUpload :uploadConfig="uploadConfig" @getImgUploadIds="uploadImgIds($event)" @getVideoUploadIds="uploadVideoIds($event)"/>const uploadConfig = ref({maxCount: 3,exParam: 'imgArr'
})// 获取图片的ids
function uploadImgIds(val) {console.log(val)
}
// 获取视频的ids
function uploadVideoIds(val) {console.log(val)
}
相关文章:
vue3移动端可同时上传照片和视频的组件
uni-app中的uni-file-picker可单独上传照片或视频,但不支持同时上传照片和视频。本篇博客使用image标签和video标签实现移动端(H5app小程序)中照片和视频的同时上传。 本篇博客采用的是照片和视频的单独上传,但可同时展示…...
PyQt入门指南二十七 QTableView表格视图组件
# 创建一个QStandardItemModel实例,用于存储表格数据model QStandardItemModel(4, 2) # 4行2列# 填充模型数据for row in range(4):for column in range(2):item QStandardItem(fRow {row}, Column {column})model.setItem(row, column, item)# 创建一个QTableVi…...
AI学习指南深度学习篇-自注意力机制(Self-Attention Mechanism)
AI学习指南深度学习篇—自注意力机制(Self-Attention Mechanism) 在深度学习的研究领域,自注意力机制(Self-Attention Mechanism)作为一种创新的模型结构,已成为了神经网络领域的一个重要组成部分…...
【JAVA毕业设计】基于Vue和SpringBoot的校园管理系统
本文项目编号 T 026 ,文末自助获取源码 \color{red}{T026,文末自助获取源码} T026,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 管…...
你对MySQL的having关键字了解多少?
在MySQL中,HAVING子句用于在数据分组并计算聚合函数之后,对结果进行进一步的过滤。它通常与GROUP BY子句一起使用,以根据指定的条件过滤分组。HAVING子句的作用类似于WHERE子句,但WHERE子句是在数据被聚合之前进行过滤,…...
【STM32编码器】【STM32】
提示:一般情况下我们会设计一个硬件电路模块来自动完成简单重复而高频的计算 文章目录 一、为什么通常情况下不使用外部中断来对编码器的脉冲进行计数?二、编码器速度测量程序设计思路三、正交编码器四、初始化流程五、STM32正交编码器输入捕获模式配置示…...
Python轴承故障诊断 (13)基于故障信号特征提取的超强机器学习识别模型
往期精彩内容: Python-凯斯西储大学(CWRU)轴承数据解读与分类处理 Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客 Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客 Pytorch-Transformer轴承故障一维信号分类(三)-CSDN博客 三十多个开源…...
VScode分文件编写C++报错 | 如何进行VScode分文件编写C++ | 不懂也能轻松解决版
分文件编写遇到的问题 分文件编写例子如下所示: 但是直接使用 Run Code 或者 调试C/C文件 会报错如下: 正在执行任务: C/C: g.exe 生成活动文件 正在启动生成… cmd /c chcp 65001>nul && D:\Librarys\mingw64\bin\g.exe -fdiagnostics-col…...
洞察前沿趋势!2024深圳国际金融科技大赛——西丽湖金融科技大学生挑战赛技术公开课指南
在当前信息技术与“互联网”深度融合的背景下,金融行业的转型升级是热门话题,创新与发展成为金融科技主旋律。随着区块链技术、人工智能技术、5G通信技术、大数据技术等前沿科技的飞速发展,它们与金融领域的深度融合,正引领着新型…...
Unity3D学习FPS游戏(4)重力模拟和角色跳跃
前言:前面两篇文章,已经实现了角色的移动和视角转动,但是角色并没有办法跳跃,有时候还会随着视角移动跑到天上。这是因为缺少重力系统,本篇将实现重力和角色跳跃功能。觉得有帮助的话可以点赞收藏支持一下!…...
C#基础知识-枚举
目录 枚举 1.分类 1.1普通枚举 1)默认情况 2)指定起始值 1.2标志枚举(Flag Enum) 位运算符与标志枚举 1)组合标志 2)检查标志 2.枚举与不同类型之间的转换 1)枚举->整型 2&#…...
系统架构设计师教程 第2章 2.1-2计算机系统及硬件 笔记
2.1计算机系统概述 ★☆☆☆☆ 计算机系统 (Computer System) 是指用于数据管理的计算机硬件、软件及网络组成的系统。 一般指由硬件子系统和软件子系统组成的系统,简称为计算机。 将连接多个计算机以实现计算机间数据交换能力的网络设备,称为计算机网…...
通过使用Visual Studio将你的程序一键发布到Docker
通过使用Visual Studio将你的程序一键发布到Docker 代码 阿里云容器镜像服务 https://www.aliyun.com/product/acr 添加Docker CE阿里云镜像仓库 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 安装Docker CE、Doc…...
vue2和vue3动态引入路由,权限控制
后端返回的路由结构(具体路由可以本地模拟) // 此路由自己本地模拟即可 const menus [{"title": "动态路由","meta": "{\"title\":\"动态路由\",\"noCache\":true}","component": "/t…...
Spring Boot:植物健康的智能守护者
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
红黑树 学习笔记
目录 1.红黑树的概念 1.1红黑树的规则 1.2红黑树的效率 2.红黑树的实现 2.1红黑树的大致结构 2.2红黑树的插入 2.2.1红黑树插入的大致过程 2.2.2情况1:变色 2.2.3情况2:单旋+变色 2.2.4情况3:双旋变色 2.3红黑树的查找…...
linux更改系统时间
测试环境和生产环境代码完全一致,但是生产环境代码碰到了问题,报错类似time expired,猜测和系统时间有关系,修改之后确实好了。测试如下: 参考:centos7时间同步教程_centos7 时间同步,如果遇到…...
B站C#刘铁猛笔记
C#——刘铁猛笔记 类、名称空间(简述) 类(class)是构成程序的主体 名称空间(namespace)以树形结构组织类(其他类型) 名称空间:名称空间是用来组织和管理类、接口、结构…...
如何使用信号发生器产生正弦波并用数字示波器进行测量
使用信号发生器产生正弦波并用数字示波器进行测量的步骤如下: 1. 准备工作 所需设备 信号发生器数字示波器探头(通常为10X衰减探头)BNC电缆和适配器(如果需要) 2. 设置信号发生器 连接 使用BNC电缆将信号发生器的…...
XJ04、消费金融|授信基本概念及其流程设计
银行是经营风险的特殊行业,而银行授信则与银行业务和风险天然相伴。它是银行与客户建立业务关系的起点,也是银行风险管理的关键环节和核心要素。若要了解银行业务,就得先了解银行的授信业务;若要理解银行经营,就得先理…...
儿童预防接种预约微信小程序springboot+论文源码调试讲解
2相关技术 2.1微信小程序 小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。尤其拥抱微信生态圈,让微信小程序更加的如虎添翼,发展迅猛。 2.2 MYSQL数据…...
nginx 修改配置
如果你的后端服务在不同的端口上运行,但静态资源访问路径相同,你可以使用 Nginx 的 location 配置来将请求转发到不同的后端服务,同时处理静态文件。这里有几种常见的方式: 方案 1: 基于路径的配置 如果所有服务的静态资源路径相…...
孤岛架构在安全性方面
孤岛架构在安全性方面的考虑主要涉及如何确保每个孤岛的安全性,同时维护整个系统的安全。 关键的安全性考虑: 1. 数据隔离和访问控制 数据隔离:每个孤岛应该有独立的数据存储,以确保数据隔离。这有助于防止数据泄露和未经授权的…...
COSCon'24 志愿者招募令:共创开源新生活!
亲爱的开源爱好者们, 第九届中国开源年会(COSCon24)即将在北京中关村国家自主创新示范区会议中心于2024年11月2日至3日隆重举行。今年的主题是“Open Source, Open Life|开源新生活”,旨在探索开源技术如何在各个领域推…...
vscode使用make编译c的问题
问题1:makefile:2: *** missing separator. Stop vscode的配置问题,看这哥们的文章即可:https://blog.csdn.net/m0_57464986/article/details/134220676 问题2:创建makefile文件 直接创建文件名为“makefile”的文件即可&#x…...
管家婆财贸ERP BB019.操作员制单日期控制
最低适用版本: 财贸系列 20.0 插件简要功能说明: 定制操作员权限功能,根据服务器日期控制系统单据新增和修改更多细节描述见下方详细文档 插件操作视频: 进销存类定制插件--操作员制单日期控制 插件详细功能文档: …...
从 Vue 2 到 Vue 3:全面升级指南
🌈个人主页:前端青山 🔥系列专栏:Vue篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Vuet篇专栏内容:Vue-从 Vue 2 到 Vue 3:全面升级指南 前言 随着前端技术的不断发展,Vue.j…...
Apache paimon表操作实战-5
维表Join Paimon支持Lookup Join语法,它用于从 Paimon 查询的数据来补充维度字段。要求一个表具有处理时间属性,而另一个表由查找源连接器支持。 Paimon 支持 Flink 中具有主键的表和append-only的表查找联接。以下示例说明了此功能。 USE CATALOG fs_catalog; CREATE TABL…...
阿里云用STS上传oss的完整程序执行流程图 和前端需要哪些参数uniapp
H5 微信小程序可用的前端直传阿里云OSS(STS临时凭证前端签名)直接下载插件 下面是原理说明: 明白了,我来详细说明前端上传文件到阿里云OSS需要携带的具体参数: 从服务器获取的 STS 凭证: // 这些参数需要从你的后端服务器获…...
决策树方法根据指定条件筛选方案
代码功能说明 条件类:Condition 类用于定义每个条件的范围,并提供一个方法 is_satisfied 来检查输入值是否满足该条件。 算法选择器类:AlgorithmSelector 类负责应用条件并记录不满足的条件。它提供方法 apply_condition 用于更新可用算法&a…...
网站建设与网页设计教程/百度网盘app下载安装
linux passwd批量修改用户密码原文:http://blog.csdn.net/xuwuhao/article/details/46618913对系统定期修改密码是一个很重要的安全常识,通常,我们修改用户密码都使用 passwd user 这样的命令来修改密码,但是这样会进入交互模式&a…...
小说网站怎么推广/seo网站优化工具大全
【问题】 现有红白蓝三个不同颜色的小球,乱序排列在一起,请重新排列这些小球,使得红白蓝三色的同颜色的球在一起。这个问题之所以叫荷兰国旗问题,是因为我们可以将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰…...
wordpress套模板教程/查询网域名查询
69、django之Form组件 本篇导航: 小试牛刀Form类常用选择插件自定义验证规则初始化数据Django的Form主要具有一下几大功能: 生成HTML标签验证用户数据(显示错误信息)HTML Form提交保留上次提交数据初始化页面显示内容一、小试牛刀…...
中国十大室内设计师/360优化大师安卓手机版下载安装
题库来源:安全生产模拟考试一点通公众号小程序 安全生产模拟考试一点通:2021年G3锅炉水处理最新解析为正在备考G3锅炉水处理操作证的学员准备的理论考试专题,每个月更新的G3锅炉水处理考试资料祝您顺利通过G3锅炉水处理考试。 1、【多选题】…...
家里电脑如何做网站/站长之家 站长工具
http://www.aboutyun.com/thread-19729-1-1.html 问题导读: 1、Spark Job Stage划分算法有哪些? 2、Task最佳计算位置算法如何理解? 3、Task任务本地算法运用场景有哪些?一、Stage划分算法 由于Spark的算子构建一般都是链式的&a…...
wordpress 微信支付插件下载/网站seo优化方法
我是卢松松,点点上面的头像,欢迎关注我哦! 这可能是最后几次发关于Alexa的文章了,因为Alexa有几个月就要关站了。以后可没什么权威的网站排行榜了! 截止到2021年12月24日Alexa统计的全球流量最大的50个网站统计,大…...