vue项目ElementUI组件中el-upload组件与图片裁剪功能组件结合使用详解

vue项目ElementUI组件中el-upload组件与裁剪功能组件结合使用,供大家参考,具体内容如下

如下图所示,点击上传组件,选择文件后,会立马弹出图片裁剪功能组件的页面

问题描述:

1.在使用upload组件中,如果修改fileList中的内容,浏览器会报错
2.获取上传的文件,传递给图片裁剪组件(在on-change中获取文件并传递个裁剪组件)
3.要获取裁剪后的图片即File文件(将裁剪后的图片返回出去)
4.获取到裁剪后的file调用上传的接口

由于el-upload组件默认使用的是
“选取文件后立即进行上传”,可通过auto-upload属性进行修改,将auto-upload设置为false;
同时也不显示已上传的文件列表,通过show-file-list属性修改,将show-file-list设置为false。

获取上传的组件说明:使用elementUI 提供的方法 on-change,获取已上传的组件

elementUI中upload组件部分属性如下:

关于裁剪组件,请看裁剪组件链接文档

本案例主要代码如下:

<el-form-item label="公司logo" prop="logo">
                    <el-upload
                            class="avatar-uploader"
                            ref="upload"
                            :action="uploadLogo"
                            :show-file-list="false"
                            :file-list="photoList"
                            :on-change="changePhotoFile"
                            :on-success="handleAvatarSuccess"
                            :before-upload="beforeAvatarUpload"
                            :headers="headerObj"
                            :auto-upload="false"
                    >
                        <img v-if="imageUrl" :src="imageUrl" class="avatar">
                        <div v-else class=" avatar-uploader-icon">
                            <div>
                                <i  class="my-icon-plus"></i>
                                <p class="my-icon-word">添加</p>
                            </div>

                        </div>
                        <!--<i v-else class="el-icon-plus avatar-uploader-icon"></i>-->
                    </el-upload>
                    <my-cropper ref="myCropper" @getFile="getFile" @upAgain="upAgain"></my-cropper>
</el-form-item>

对应的方法

 changePhotoFile(file, fileList){
                if (fileList.length > 0) {
                    this.photoList = [fileList[fileList.length - 1]]
                }
                this.handleCrop(file);
            },
   handleCrop(file){
                this.$nextTick(()=>{
                    this.$refs.myCropper.open(file.raw || file)
                })
            },
            // 点击弹框重新时触发
            upAgain(){
                this.$refs['upload'].$refs["upload-inner"].handleClick();
            },
            getFile(file){
                const formData = new FormData();
                formData.append("file",file)
                uploadSelfCompanyLogo(formData).then(res =>{
                    if (res.code === 0) {
                        this.companyInfo.logo = res.filename;
                        this.companyInfo.imageUrl = res.url;
                        this.imageUrl = res.url;
                        //上传成功后,关闭弹框组件
                        // this.handleCrop(file);
                        this.$refs.myCropper.close()

                    } else {
                        this.$message.error('上传出错');
                    }
                })
       
            },

整个vue代码,包含上面的代码

<template>
    <div class="form-out">
        <el-form
                :rules="rules"
                :model="companyInfo"
                class="form"
                ref="registForm"
                label-position="left"
                label-width="92px"
        >
            <div class="personal-info">
                <p class="tag">
                    <span class="light-slash">/</span>
                    <span class="slash">/</span>
                    <span class="tag-main">公司信息</span>
                    <span class="slash">/</span>
                    <span class="light-slash">/</span>
                </p>

                <el-form-item label="公司全称" prop="companyName">
                    <span class="com-name">{{companyInfo.companyName}}</span>
                </el-form-item>
                <el-form-item label="公司简称" prop="shortened">
                    <el-input
                            style="width: 540px;height: 42px"
                            v-model="companyInfo.shortened"
                            placeholder="请填写当前公司简称"
                            clearable
                    ></el-input>
                </el-form-item>
                <el-form-item label="行业领域" prop="industry">
                    <el-select
                            class="inputSelect"
                            v-model="companyInfo.industry"
                            placeholder="请选择行业领域"
                            clearable
                    >
                        <el-option
                                v-for="item in industryOptions"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value"
                        ></el-option>
                    </el-select>
                </el-form-item>

                <el-form-item label="公司规模" prop="scale">
                    <el-select
                            class="inputSelect"
                            v-model="companyInfo.scale"
                            placeholder="请选择公司规模"
                            clearable
                    >
                        <el-option
                                v-for="item in scaleOptions"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value"
                        ></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="公司性质" prop="nature">
                    <el-select
                            v-model="companyInfo.nature"
                            placeholder="请选择公司性质"
                            clearable
                    >
                        <el-option
                                v-for="item in natureOptions"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value"
                        ></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="公司logo" prop="logo">
                    <el-upload
                            class="avatar-uploader"
                            ref="upload"
                            :action="uploadLogo"
                            :show-file-list="false"
                            :file-list="photoList"
                            :on-change="changePhotoFile"
                            :on-success="handleAvatarSuccess"
                            :before-upload="beforeAvatarUpload"
                            :headers="headerObj"
                            :auto-upload="false"
                    >
                        <img v-if="imageUrl" :src="imageUrl" class="avatar">
                        <div v-else class=" avatar-uploader-icon">
                            <div>
                                <i  class="my-icon-plus"></i>
                                <p class="my-icon-word">添加</p>
                            </div>

                        </div>
                        <!--<i v-else class="el-icon-plus avatar-uploader-icon"></i>-->
                    </el-upload>
                    <my-cropper ref="myCropper" @getFile="getFile" @upAgain="upAgain"></my-cropper>
                </el-form-item>
                <el-form-item label="公司简介" prop="intro">
                    <el-input type="textarea" v-model="companyInfo.intro"></el-input>
                </el-form-item>
            </div>

            <div class="submit">
                <el-button
                        class="next-button"
                        type="primary"
                        size="medium"
                        :class="[nextFlag ?'next-button-bg-blue':'next-button-bg-grew']"
                        @click="companyRegister">
                    确定
                </el-button>
                <span class="return-back" @click="returnBackFun"> 返回上一步 </span>
            </div>
        </el-form>

    </div>
</template>

<script>
    import debounce from "../../../common/debounce";
    import DataDict from "../../../common/DataDict";
    import {createCompanyBase,uploadSelfCompanyLogo} from  '../../../network/request'
    import MyCropper from "./cropper.vue"
    export default {
        name: "ComFormThree",
        components:{MyCropper},
        data(){
            //信用代码验证
            var checkCreditCode = (rules, value, callback) => {
                let position = new RegExp(/^([0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}|[1-9]\d{14})$/);
                if(!position.test(value)) {
                    callback(new Error('请输入正确的统一社会信用代码!'));
                } else {
                    callback();
                }
            }
            return{
                nextFlag:false,
                uploadLogo: process.env.VUE_APP_BASE_URL + '/business/pub/iface/uploadCompanyLogo',//上传共公司logo地址
                imageUrl: '',
                companyInfo: {
                    companyName: '',
                    logo:'',
                    creditCode: '',
                    shortened: '',
                    industry:null,
                    scale:null,
                    nature:null,
                    companyId:null,
                    imageUrl:'',
                    intro:''
                },
                photoList:[],
                industryOptions:DataDict.industryOptions,//行业领域数据字典
                scaleOptions:DataDict.scaleOptions,//公司规模数据字典
                natureOptions:DataDict.natureOptions,//公司性质数据字典
                rules: {
                    companyName:[
                        { required: true},
                    ],
                    creditCode:[
                        { required: true, message: '请输入统一社会信用代码', trigger: 'blur' },
                        { validator: checkCreditCode, trigger: 'blur' }
                    ],
                    logo:[{ required: true},],
                    intro:[{ required: true, message: '请填写公司简介',trigger: 'blur' },],
                    shortened:[{ required: true, message: '请填写公司简称',trigger: 'blur'},],
                    industry:[{ required: true,
                        message: '请选择行业领域',
                        trigger: 'change'},],
                    scale: [
                        {
                            required: true,
                            message: '请选择公司规模',
                            trigger: 'change'
                        }
                    ],
                    nature: [
                        {
                            required: true,
                            message: '请选择公司性质',
                            trigger: 'change'
                        }
                    ],
                },
            }
        },
        mounted() {
           // console.log("this.$store.personInfo.companyName",this.$store.getters.personInfo.companyName);
                this.companyInfo.companyName = this.pCompanyName;
            },
        activated() {
            this.companyInfo.companyName = this.pCompanyName;
        },
        computed:{
            pCompanyName(){
                return this.$store.getters.personInfo.companyName;
            }
        },
     watch:{
         companyInfo: {
             handler(val){
                 (val.companyName !== ''
                     && val.creditCode !=='' && val.creditCode.length>0
                     && val.logo !== '' && val.logo.length>0
                     && val.shortened !== '' && val.shortened.length >0
                     && val.industry !== null
                     && val.nature !== null
                     && val.scale != null
                 )
                     ? this.nextFlag = true : this.nextFlag = false;
             },
             deep: true
         }
     },
        /*mounted() {
            console.log("uploadLogo====",this.uploadLogo);
        },*/
        methods:{
            //上传图片触发
            handleCrop(file){
                this.$nextTick(()=>{
                    this.$refs.myCropper.open(file.raw || file)
                })
            },
            // 点击弹框重新时触发
            upAgain(){
                this.$refs['upload'].$refs["upload-inner"].handleClick();
            },
            getFile(file){
                const formData = new FormData();
                formData.append("file",file)
                uploadSelfCompanyLogo(formData).then(res =>{
                    if (res.code === 0) {
                        this.companyInfo.logo = res.filename;
                        this.companyInfo.imageUrl = res.url;
                        this.imageUrl = res.url;
                        //上传成功后,关闭弹框组件
                        // this.handleCrop(file);
                        this.$refs.myCropper.close()

                    } else {
                        this.$message.error('上传出错');
                    }
                })
               // this.$refs.upload.submit();
            },
            companyRegister:debounce(function () {
                this.doCompanyRegister();
            },500),
            //下一步
            doCompanyRegister(){
                this.$store.commit('addcompanyObjInfo',this.companyInfo);
                createCompanyBase(this.companyInfo).then(res =>{
                    if (res.code === 0 && res.msg === 'success') {
                        console.log("创建成功");
                        /*this.$message.success('公司创建成功~');
                        this.$router.push("/client/auditPage");*/
                    }
                })
            },
            //头像上传成功之后的方法,进行回调
            handleAvatarSuccess(res,file) {
                if (res.code === 0) {
                    this.companyInfo.logo = res.filename;
                    this.companyInfo.imageUrl = res.url;
                    this.imageUrl = res.url;
                   // this.handleCrop(file);
                } else {
                    this.$message.error('上传出错');
                }
            },
            //上传图片时会被调用
            changePhotoFile(file, fileList){
                if (fileList.length > 0) {
                    this.photoList = [fileList[fileList.length - 1]]
                }
                this.handleCrop(file);
            },
            //头像上传之前的方法
            beforeAvatarUpload(file) {
                const isJPG =
                    file.type === 'image/jpeg' ||
                    'image/jpg' ||
                    'image/gif' ||
                    'image/png';
                const isLt6M = file.size / 1024 / 1024 < 6;

                if (!isJPG) {
                    this.$message.error(
                        '上传头像图片只能是 JPG、JPEG、GIF或PNG 格式!'
                    );
                }
                if (!isLt6M) {
                    this.$message.error('上传头像图片大小不能超过 6MB!');
                }
                console.log("275==",file)

                return isJPG && isLt6M;
            },
            //返回上一步
            returnBackFun(){
                let obj = {formType:3}
                this.$emit("returnBackTwo",obj)
            }
        }
    }
</script>

<style scoped lang="less">
    .form-out{
        width: 1100px;
        border-radius: 10px;
        background: #fff;
        .form {
            padding: 40px 120px;
            margin: 0 auto;
            display: table;
            .tag {
                text-align: center;
                margin: 0 0 40px 0;
                .tag-main{
                    display: inline-block;
                    font-size:16px;
                    font-family:PingFangSC-Semibold,PingFang SC;
                    font-weight:600;
                    color:#222222;
                    padding: 0 10px
                }
                .slash {
                    color: #437FFF;
                    font-weight: bold;
                    font-size: 16px;
                }
                .light-slash {
                    color: #437fff;
                    font-weight: bold;
                    font-size: 16px;
                    opacity: 0.5;
                }
            }
            .com-name{
                display: inline-block;
                /*width:224px;*/
                height:22px;
                font-size:16px;
                font-family:PingFangSC-Regular,PingFang SC;
                font-weight:400;
                color:rgba(51,51,51,1);
                line-height:22px;
            }
            .avatar {
                width: 80px;
                height: 80px;
              /*  border-radius: 30px;*/
                vertical-align: middle;
            }
            .avatar-desc {
                color: #999;
                font-size: 12px;
                padding-left: 10px;
            }
            .tag-other {
                margin-top: 40px;
            }
            .submit {
                display: flex;
                justify-content: center;
                margin-top: 40px;
                .submit-button {
                    background: #437FFF;
                    width: 390px;
                    margin-top: 20px;
                    font-size: 22px;
                }
                .next-button{
                    width:140px;
                    height:42px;
                    border-radius:6px;
                    font-size:16px;
                    color: #999999;
                    border: 1px solid transparent;
                    font-family:PingFangSC-Regular,PingFang SC;
                    font-weight:400;
                }
                .return-back{
                    display: inline-block;
                    height:42px;
                    line-height: 42px;
                    width:70px;
                    font-size:14px;
                    font-family:PingFangSC-Medium,PingFang SC;
                    font-weight:500;
                    color:rgba(102,102,102,1);
                    margin-left: 50px;
                    &:hover{
                        cursor: pointer;
                    }
                }
                .next-button-bg-grew{
                    background:#E5E5E5;
                }
                .next-button-bg-blue{
                    background:#437FFF;
                    color:#FFFFFF
                }

            }
        }
    }
</style>
<style scoped>

    .el-input__inner {
        width:540px;
        height:42px;
        background:rgba(249,249,249,1);
        border-radius:2px;
        border: 1px solid transparent;
    }
    .el-form-item__label{
        font-size:16px;
        font-family:PingFangSC-Regular,PingFang SC;
        font-weight:400;
        color:#222222;
    }

    input::-webkit-input-placeholder {
        height:21px;
        font-size:15px;
        font-weight:400;
        color:rgba(204,204,204,1);
        line-height:21px;
    }
    input::-ms-input-placeholder {
        height:21px;
        font-size:15px;
        font-weight:400;
        color:rgba(204,204,204,1);
        line-height:21px;
    }
    .my-icon-plus{
        background: url("../../../assets/img/upload/upload_plus.png") no-repeat;
        background-size: 24px 24px;
        width: 24px;
        height: 24px;
        display: inline-block;
    }
    .my-icon-word{
        height:17px;
        font-size:12px;
        font-family:PingFangSC-Regular,PingFang SC;
        font-weight:400;
        color:#437FFF;
        line-height:17px;
    }
</style>
<style >
    .form-out .avatar-uploader .el-upload {
        /*border: 1px dashed #d9d9d9;*/
        border: 1px dashed #437FFF;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
      /*  overflow: hidden;*/
    }
    .form-out .avatar-uploader .el-upload:hover {
        border-color: #409EFF;
    }
    .form-out .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 80px;
        height: 80px;
        text-align: center;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .form-out .avatar {
        width: 80px;
        height: 80px;
        display: block;
    }
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Vue-cropper 图片裁剪的基本原理及思路讲解

    一:裁剪的思路: 1-1,裁剪区域:需要进行裁剪首先需要形成裁剪区域,裁剪区域的大小和我们的鼠标移动的距离相关联,鼠标移动有多远,裁剪区域就有多大.如下图: 1-2 裁剪区域的宽和高的计算: 如上图,鼠标的横向移动距离和纵向移动距离就形成了裁剪区域的宽和高.那么裁剪区域的宽和高的计算是:当我们点下鼠标时,就能够通过event事件 对象获取鼠标点击位置,e.clientX 和 e.clientY; 当鼠标进行移动的时候,也能通过event获取鼠标的位置,通过两次鼠标位置的改变,就能够获得 鼠标移动

  • vue-image-crop基于Vue的移动端图片裁剪组件示例

    本文介绍了vue-image-crop基于Vue的移动端图片裁剪组件示例,分享给大家,具体如下: 代码地址:https://github.com/jczzq/vue-image-crop vue-image-crop 基于Vue的移动端图片裁剪组件 组件使用URL.createObjectURL()等新特性,使用前注意兼容问题.IE >= 10 注意:该组件适用于 PC 端,不推荐手机端使用. 功能预览 快速开始 安装Node >= 8.9.0(推荐LTS = 8.11.0) # 安装 vue

  • vue项目实现添加图片裁剪组件

    本文实例为大家分享了vue项目添加图片裁剪组件的具体代码,供大家参考,具体内容如下 功能如下图所示: 1.安装命令如下 npm i vue-cropper --save 2.调用组件,引入vue-cropper import { VueCropper } from "vue-cropper"; 3.封装组件代码如下:cropper.vue <template>   <div class="cropper_model">     <el-

  • cropper js基于vue的图片裁剪上传功能的实现代码

    前些日子做了一个项目关于vue项目需要头像裁剪上传功能,看了一篇文章,在此基础上做的修改完成了这个功能,与大家分享一下.原文:http://www.jb51.net/article/135719.htm 首先下载引入cropper js, npm install cropper js --save 在需要的页面引入:import Cropper from "cropper js" html的代码如下: <template> <div id="demo&quo

  • vue实现图片裁剪后上传

    本文实例为大家分享了vue实现图片裁剪后上传的具体代码,供大家参考,具体内容如下 一.背景 目前负责的系统(商城后台管理系统)里面有这么一个需求,为了配合前台的展示,上传的商品图片比较必须是1:1的正方形.(其它地方有时会有5:4或者16:9的需求,但较少).所以需要对上传的图片先进行裁剪,并且按要求只能裁剪为1:1,然后在进行上传. 当然,为了兼容系统其它地方有5:4或者16:9的图片比例需求,需要给出一个参数,可以随时控制图片裁剪的比例. 二.使用什么插件实现 使用 vue-cropper

  • Vue图片裁剪组件实例代码

    示例: tip: 该组件基于vue-cropper二次封装 安装插件 npm install vue-cropper yarn add vue-cropper 写入封装的组件 <!-- 简易图片裁剪组件 --- 二次封装 --> <!-- 更多api https://github.com/xyxiao001/vue-cropper --> <!-- 使用:传入图片 比例 显示隐藏.方法:监听底部按钮点击即可 ---更多props查询文档自行添加 --> <temp

  • 基于cropper.js封装vue实现在线图片裁剪组件功能

    效果图如下所示, github:demo下载 cropper.js github:cropper.js 官网(demo) cropper.js 安装 npm或bower安装 npm install cropper # or bower install cropper clone下载:下载地址 git clone https://github.com/fengyuanchen/cropper.git 引用cropper.js 主要引用cropper.js跟cropper.css两个文件 <scri

  • 详解vue项目中实现图片裁剪功能

    演示地址 https://my729.github.io/picture-crop-demo/dist/#/ 前言 vue版本:3.6.3 https://cli.vuejs.org/zh/ cropperjs: 1.5.1 https://github.com/fengyuanchen/cropperjs elementUI https://element.eleme.io/#/zh-CN 使用 cropperjs插件 和 原生canvas 两种方式实现图片裁剪功能 使用cropperjs插件

  • vue 图片裁剪上传组件的实现

    先看一下总体效果: 上传文件做了大小和类型的限制,在动图中无法展现出来. 使用file类型的input实现选择本地文件 但是浏览器原生的文件上传按钮的颜值不尽人意,而且按钮上的文字是无法改变的,我需要把这个上传文件的按钮改造一下. 方法1:使用label元素来触发一个隐藏的file类型的 input元素:(缺点:在多人开发时,可能出现重复的元素id,导致难以预料的bug) <input type="file" id='up_file_input' v-show='false' &

  • vue图片裁剪插件vue-cropper使用方法详解

    本文实例为大家分享了vue图片裁剪插件vue-cropper的使用方法,供大家参考,具体内容如下 我在网上找了很多关于vue裁剪图片的文章,demo都太长了,实在是太长了.有些还都看不懂,最后还是用了个大佬的demo,但是项目实践过程中还是有问题没解决.先介绍吧.效果是下面这样的, 我这里采用了4:3的固定比例进行裁剪,裁剪后的效果 但是裁剪后的图片路径是base64,超级长的路径,最终还是需要处理地址传给后端的,项目用oss处理图片,最终获得一个类似于aad68a8fd577464dbcdea

随机推荐