【vue/uniapp】使用 uni.chooseImage 和 uni.uploadFile 实现图片上传(包含样式,可以解决手机上无法上传的问题)

引入:
之前写过一篇关于 uview 1.x 版本上传照片 的文章,但是发现如果是在微信小程序的项目中嵌入 h5 的模块,这个 h5 的项目使用 u-upload 的话,图片上传功能在电脑上正常,但是在手机的小程序上测试就不会生效,点击上传加号按钮毫无反应。
解决方法:
现在最终的解决方法是,使用 uniapp 的 uni.chooseImage 来选择照片,使用 uni.uploadFile 来上传图片,其他所有的样式和逻辑都自己来实现,最终的效果长这样:

代码与解析:
单独写一个组件,先实现样式:

<template>
    <view class="meeting-image">
        <view class="title">
            <text></text>
            <!-- 展示图片张数 -->
            <text style="color: #a1a1a1;">({{ list.length }}/9)</text>
        </view>
        <view class="img_wrap flex-row flex-justify-between">
            <view class="img_box" v-for="(item, index) in list" :key="index">
                <!-- 展示上传之后的图片 -->
                <image :src="item.imgUrl" class="pic" mode="aspectFill" @click="previewImage(index)" />
                <!-- 删除图标 -->
                <!-- 这里的删除图标叉叉是用的在线网址,$public 是挂载在原型上的,可以自定义 -->
                <image 
                    :src="`${$public()}/project-meeting/icon_20_close.png`" 
                    class="close"
                    @click.stop="handleDeleteImg(index, item)" />
            </view>
            <!-- 上传的方框 -->
            <view 
                class="upload-box" 
                @click="chooseImg" 
                v-if="list.length !== 9 && isSponsorUserFlag == 1"
            ></view>
        </view>
        <u-toast ref="uToast" />
    </view>
</template>
.meeting-image {
    .title {
        font-size: 32rpx;
        line-height: 40 rpx;

        text:nth-of-type(1) {
            color: #ff3f30;
            padding-right: 4rpx;
        }

        text:nth-of-type(3) {
            padding-left: 12rpx;
            color: #cccccc;
        }
    }

    .img_wrap {
        flex-wrap: wrap;

        &::after {
            width: calc((100% - 40rpx) / 3);
            display: block;
            content: '';
        }

        .img_box {
            margin-top: 20rpx;
            position: relative;
            width: calc((100% - 40rpx) / 3);
            height: 220rpx;

            .pic {
                width: 100%;
                height: 100%;
                object-fit: cover;
                border-radius: 14rpx;
            }

            .close {
                position: absolute;
                top: -8rpx;
                right: -8rpx;
                width: 40rpx;
                height: 40rpx;
            }
        }

        .upload-box {
            position: relative;
            width: calc((100% - 40rpx) / 3);
            height: 220rpx;
            border: 1px solid #e5e5e5;
            box-sizing: border-box;
            position: relative;
            border-radius: 14rpx;
            margin-top: 20rpx;

            &::after {
                display: block;
                content: '';
                width: 1px;
                height: 96rpx;
                background-color: #e5e5e5;
                position: absolute;
                left: 105rpx;
                top: 50rpx;
            }

            &::before {
                display: block;
                content: '';
                width: 96rpx;
                height: 1px;
                background-color: #e5e5e5;
                position: absolute;
                right: 60rpx;
                top: 100rpx;
            }
        }
    }
}

js 逻辑部分,我这里后端提供的 api 有上传(查询文件地址),即代码中的 previewUrl ,删除的实现方法是在本地进行的,是对数组进行 splice 之后,再将最新的图片数组保存进大数组一次,最后再进行上传,注释写的很详细,方便以后回顾查看。

简单解释:

chooseImg 是最先执行的函数,即点击上传按钮时执行,进来判断是不是数量超过了 9 张,没超过就往下走;
使用 uni.chooseImage 进行图片选择功能,配置相应参数和值,选择成功,走到 then 的成功回调里,回显照片,此时调接口 previewUrl 来上传获取图片id;
然后将图片保存进数组中

<script>
import { BASE_URL } from '@/pages/workTable/utils/constant'
import { previewUrl } from '@/pages/workTable/utils/api.js'

export default {
    name: 'meeting-image',
    // 接收参数
    props: {
        fileList: {
            type: Array,
            default: []
        },
        // 用于该页面有很多项,而每一项都需要传一组图片的页面
        subItem: {

        },
        // 用于只传一组图片的页面
        picListArr: {

        },
        picList: {

        }
    },
    data() {
        return {
            list: [],
            count: 9,
        }
    },

    computed: {},
    methods: {
        // 预览功能暂时有问题
        previewImage(index) {
            console.log('预览', this.list.map(el => el.imgUrl));
            uni.previewImage({
                current: index,
                urls: this.list.map(el => el.imgUrl)
            })
        },
        // 点击上传按钮触发
        chooseImg() {
            // 如果大于 9 张就不触发底下的 uni.chooseImage
            if (this.count == 0) {
                this.$refs.uToast.show({
                    title: '最多能上传9张照片',
                    duration: 2000
                })
                return
            }
            uni.chooseImage({
                // 最多可以选择的图片张数,默认9
                count: this.count,
                // original 原图,compressed 压缩图,默认二者都有
                sizeType: ['original', 'compressed'],
                // album 从相册选图,camera 使用相机,默认二者都有
                sourceType: ['album', 'camera'],
                success: res => {
                    // console.log('res',res);
                    uni.showLoading({
                        title: '上传中'
                    })
                    Promise.all(
                        res.tempFilePaths.map(item => {
                            return this.uploadFile({
                                filePath: item
                            })
                        })
                    )
                        .then(re => {
                            uni.hideLoading()
                            // let fileList = []
                            re.map((el, index) => {
                                let data = JSON.parse(el.data)
                                // 用于上传成功后照片回显
                                // console.log('data',data.data);
                                previewUrl(data.data).then(res => {
                                    console.log('我要预览图片', res); this.list.push({ fileUrl: data.data, imgUrl: res.data })
                                    setTimeout(() => {
                                        console.log('this.list', this.list);
                                        this.saveFile(this.list)
                                    }, 800)
                                })
                            })
                        })
                        .catch(err => {
                            console.log('err', err);
                            this.$refs.uToast.show({
                                title: '上传失败',
                                duration: 2000
                            })
                            uni.hideLoading()
                        })
                },
                fail: () => { }
            })
        },
        // 上传图片
        uploadFile({ filePath }) {
            return new Promise((resolve, reject) => {
                uni.uploadFile({
                    url: `${BASE_URL}/mobilemanage/api/common/upload?typeEnum=IMAGE`,
                    filePath: filePath,
                    name: 'file',
                    header: {
                        'site3-f-ue': uni.getStorageSync('site3-f-ue')
                    },
                    formData: {
                        typeEnum: "IMAGE",
                    },
                    success: res => {
                        console.log('调用上传接口的结果', res);
                        resolve(res)
                    },
                    fail: error => {
                        reject(error)
                    }
                })
            })
        },
        // 将图片保存进数组
        saveFile(list) {
            console.log('aaaaaaaaaa', list);
            // 子组件拿接到的父组件传过来的值,subItem 是每一项的数据,里面有 picList 和 picListArr
            console.log('父组件传过来的subItem', this.subItem);
            // 每一项都需要上传照片这种情况才需要用到 subItem
            if (this.subItem) {
                console.log('有 subItem 的情况');
                let subItem = this.subItem
                subItem.picList = []
                subItem.picListArr = []

                list.map(async item => {
                    console.log('bbbbbbbb', item);
                    subItem.picList.push({
                        fileUrl: item.fileUrl
                    })
                    console.log('subItem.picList', subItem.picList);
                })
                console.log('subItem.picList', subItem.picList);
                subItem.picList.map(item => {
                    subItem.picListArr.push(item.fileUrl)
                })
                console.log('subItem.picListArr', subItem.picListArr);
            } else {
                console.log('没有subItem的情况', list);
                // 只需要上传一组图片
                let picList = this.picList
                let picListArr = this.picListArr

                picList = []
                picListArr = []
                // console.log('list',list);
                list.map(async item => {
                    console.log('qqqqqqqqqqqq', item);
                    picList.push({
                        fileUrl: item.fileUrl
                    })
                })
                this.$emit('getPicList', picList)
                console.log('照片列表', picList);
            }
        },
        // 删除图片
        handleDeleteImg(index, item) {
            this.list.splice(index, 1)
            this.saveFile(this.list)
            this.$refs.uToast.show({
                title: '删除成功',
                duration: 2000
            })
        }
    },
    watch: {
        // 监视当前图片数组长度,增减张数显示
        fileList: {
            handler: function (value) {
                this.list = value
                this.count = 9 - this.list.length
            },
            deep: true,
            immediate: true
        }
    }
}
</script>

使用的时候,父组件进行调用传值:

import uploadImage from '../components/upload-image'
components: {
    uploadImage
},
<upload-image 
    :fileList="subItem.picList" 
    :subItem="subItem" 
    :projectMeetingId="1"
    :isSponsorUserFlag="1"
></upload-image>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/288150.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

声明式管理方(yaml)文件

声明式管理方(yaml)文件: 1、适合对资源的修改操作 2、声明式管理依赖于yaml文件&#xff0c;所有的内容都在yaml文件当中。 3、编辑好的yaml文件需要依靠陈述是还是要依靠陈述式的命令发布到k8s集群当中 create只能创建&#xff0c;不能更新。从指定yaml文件中读取配置&#…

【华为机试】2023年真题B卷(python)-考古问题

一、题目 题目描述&#xff1a; 考古问题&#xff0c;假设以前的石碑被打碎成了很多块&#xff0c;每块上面都有一个或若干个字符&#xff0c;请你写个程序来把之前石碑上文字可能的组合全部写出来&#xff0c;按升序进行排列。 二、输入输出 三、示例 示例1: 输入输出示例仅供…

java练习题之常用类Object类,包装类

常用类 应用知识点&#xff1a; Object类 包装类 习题&#xff1a; 1&#xff1a;(Object 类)仔细阅读以下代码&#xff0c;写出程序运行的结果&#xff1b;并简述 和 equals 的区别。 true false 是判断两个变量或实例是不是指向同一个内存空间。 比较两个引用类型的地址&…

声明式管理方法

声明式管理方法&#xff08;yaml&#xff09;文件&#xff1a; 1&#xff0c;适合对资源的修改操作 2&#xff0c;声明式管理依赖于yaml文件&#xff0c;所有的内容都在yamI文件当中 3&#xff0c;编辑好的yaml文件&#xff0c;还是要依靠陈述式命令发布到k8s集群当中 发布的…

Spring见解 1

1.Spring概述 1.1.Spring介绍 ​ Spring是轻量级Java EE应用开源框架&#xff08;官网&#xff1a; http://spring.io/ &#xff09;&#xff0c;它由Rod Johnson创为了解决企业级编程开发的复杂性而创建 1.2.简化应用开发体现在哪些方面&#xff1f; IOC 解决传统Web开发中…

SpringBoot—支付—微信

一、支付流程 1.1、支付准备 1.获取商户号 微信商户平台 申请成为商户 > 提交资料 > 签署协议 > 获取商户号 2.获取 AppID 微信公众平台 注册服务号 > 服务号认证 > 获取APPID > 绑定商户号 3.申请商户证书 登录商户平台 > 选择 账户中心 > 安全…

Kali Linux实现UEFI和传统BIOS(Legacy)引导启动

默认Kali linux安装会根据当前启动的引导模式进行安装 例:以UEFI引导启动安装程序,安装后仅能在UEFI引导模式下进入系统 安装Kali系统 这边基于VirtualBox虚拟机镜像实战操作 首先创建一个Kali虚拟机 这里需要注意,把启动 EFI (只针对某些操作系统)选项勾选上,内存、处理器…

I.MX6ULL_Linux_驱动篇(52)linux CAN驱动

CAN 是目前应用非常广泛的现场总线之一&#xff0c;主要应用于汽车电子和工业领域&#xff0c;尤其是汽车领域&#xff0c;汽车上大量的传感器与模块都是通过 CAN 总线连接起来的。 CAN 总线目前是自动化领域发展的热点技术之一&#xff0c;由于其高可靠性&#xff0c; CAN 总线…

酷雷曼精彩亮相CMC 2023中国元宇宙大会,助力云上VR直播

12月23日&#xff0c;2023中关村论坛系列活动——CMC 2023中国元宇宙大会在石景山首钢园冰壶馆成功举办。酷雷曼VR作为元宇宙领域代表企业之一受邀出席会议&#xff0c;分享元宇宙技术研发成果及应用方案&#xff0c;并为大会提供VR直播技术支持。 大咖云集&#xff0c;共商元宇…

数据库进阶教学——主从复制(Ubuntu22.04主+Win10从)

目录 一、概述 二、原理 三、搭建 1、备份数据 2、主库配置Ubuntu22.04 2.1、设置阿里云服务器安全组 2.2、修改配置文件 /etc/my.cnf 2.3、重启MySQL服务 2.4、登录mysql&#xff0c;创建远程连接的账号&#xff0c;并授予主从复制权限 2.5、通过指令&#xff0c;查…

进程终结之道:kill与pskill的神奇战斗

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 进程终结之道&#xff1a;kill与pskill的神奇战斗 前言基本用法kill命令&#xff1a;基础语法&#xff1a;选项&#xff1a;示例&#xff1a; pskill命令&#xff1a;基础语法&#xff1a;选项&#x…

kbdnecnt.DLL文件缺失,软件或游戏无法启动运行,怎样快速修复?

不少人都在问“kbdnecnt.DLL文件”是什么&#xff1f;为什么电脑总是报错提示说“kbdnecnt.DLL文件缺失&#xff0c;软件无法启动”&#xff1f; 首先&#xff0c;先来了解“kbdnecnt.DLL文件”是什么&#xff1f; kbdnecnt.DLL是Windows操作系统中的一个动态链接库文件&#…

JOSEF约瑟 断电延时继电器 SRTD-220VDC-2H2D 导轨安装

系列型号&#xff1a; SRTD-24VDC-1H1D断电延时继电器&#xff1b;SRTD-110VDC-1H1D断电延时继电器&#xff1b; SRTD-220VDC-1H1D断电延时继电器&#xff1b;SRTD-110VAC-1H1D断电延时继电器&#xff1b; SRTD-220VAC-1H1D断电延时继电器&#xff1b;SRTD-24VDC-2H断电延时继电…

考PMP真的有用吗?看完立马不犹豫了!

其实我个人觉得在你考证之前&#xff0c;值得反思的是&#xff1a;为什么要考这个证书&#xff1f;是因为公司需要&#xff1f;个人职业发展&#xff1f;还是受到新闻报道或广告的影响&#xff0c;觉得PMP证书有价值&#xff0c;只是想了解一下。这样就会导致很多人会说&#x…

golang并发编程-channel

在golang 并发编程里&#xff0c;经常会听到一句话&#xff1a;不要通过共享内存进行通信&#xff0c;通过通信来共享内存。下面我们会介绍下channel, 通过源码的方式去了解channel是怎么工作的。 基本结构 流程图 代码解读 type hchan struct {qcount uint // …

HubSpot邮件营销好用吗?

HubSpot的邮件营销工具通常被认为是非常强大和易用的&#xff0c;但用户的体验和满意度会因个人需求和经验而异。以下是一些通常与HubSpot邮件营销工具相关的优势&#xff1a; 全面的功能&#xff1a; HubSpot的邮件营销工具提供了丰富的功能&#xff0c;包括电子邮件自动化、…

西门子消防主机电源维修控制器BCB8005

火灾自动报警部分主要由各个部位的火灾探测器及手动报警按钮、消火栓按钮等设备组成。火灾探测器就如同火灾报警系统的“眼睛”,通过各自的火灾探测器采集现场的火警信号&#xff0c;实时传送给火灾报警控制器&#xff0c;火灾报警控制器进行各种智能的分析判断后发出火灾报警&…

【力扣题解】P700-二叉搜索树中的搜索-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P700-二叉搜索树中的搜索-Java题解&#x1f30f;题目描述&#x1f4a1;题解&#x1f…

Python 从入门到精通之通俗易懂学闭包

系列 Python从入门到精通之安装与快速入门-CSDN博客 Python从入门到精通之基本数据类型和变量-CSDN博客 Python从入门到精通之集合&#xff08;List列表、Tuple元组、Dict字典、Set&#xff09;-CSDN博客 Python从入门到精通之条件语句、循环语句和函数-CSDN博客 Python从…

【双指针算法】-- 左右指针

左右指针 前言一、双指针算法二、左右指针1.用于在已排序数组中找到两个数使其和为特定值2.在字符串中判断是否为回文 总结 前言 今天在刷Leetcode的时候觉得自己双指针掌握的还是不错的记录一下,写个学习笔记,也方便以后翻阅,如果也帮助到你了,那真是太好啦! 本篇介绍的是左右…