Vue实现自动生成二维码并实现复制下载功能:

  • Post author:
  • Post category:vue




1、安装依赖:
// 二维码组件
npm install vue-qr --save

//实现复制二维码链接
npm install clipboard --save


2、使用组件:

在这里插入图片描述

<!-- 
    二维码生成组件弹框

    使用:
        <template>
            .....
            //二维码
            <QRCode  ref="qrcode" />
            ...
        </template>

        <script>
            import QRCode from '@/components/qrcode'

            export default {
                data() {
                    return {}
                },
                components: { QRCode },
                methods: {
                    // 按钮点击事件=>生成二维码
                    generateQRCodeBtn() {
                    	let param={...this.siteInfoList}
                        this.$refs.qrcode.init(param,'','站点二维码') //(二维码内容,二维码下载名称)
                    },
                }
            }
        </script>
 -->

<template>
    <el-dialog :visible.sync="erCode" center :title="title" width="15%" :fullscreen="fullscreen">
    	<i class="el-icon-full-screen fullscreen" @click="isFullScreen()"></i>
        <div class="ebox">
            <vue-qr ref="Qrcode" :text="dataObj.text" :logoSrc="dataObj.logo" qid="testQrId">
            </vue-qr>
        </div>
        <div class="eboxBtn">
            <a class="tag-copy" :data-clipboard-text="dataObj.text" @click="copyShareLink()">复制二维码</a>
            <a :href="exportLink" @click="downloadImg()" :download="downloadFilename">下载二维码</a>
        </div>
        <section class="footer">
            <el-button type="danger" @click="cancelBtn()">取消</el-button>
        </section>
    </el-dialog>
</template>

<script>
import VueQr from 'vue-qr'// 二维码组件
import Clipboard from 'clipboard'// 复制粘贴组件

export default {
    data() {
        return {
            erCode: false,//弹框显示与隐藏
            title: '二维码',//弹框名称

            dataObj: {
                text: '',//二维码信息
                // logo: require('@/assets/img/avatar5.png')
                logo: ''
            },
            exportLink: '',
            downloadFilename: '',//下载图片名称
			
			fullscreen: false,
        }
    },
    components: { VueQr },
    methods: {
        // 生成二维码
    	init(text, type, title) {
      		if (!text) {
        		this.$message.warning('二维码的内容不能为空!!!')
        		return
      		}
       		//如果要跳转到想要的页面this.dataObj.text=页面地址+参数
      		if (type == 'presetInfo_appointCode') {
        		//预置信息=>生成预约码
        		text.jgid = text.deptId, text.bdid = text.stationId, text.fhdw = text.consigner
        		text.shdw = text.consignee, text.pm = text.variety, text.yxq = text.usefulTime
        		this.dataObj.text = "https://xxx/index.html#/" + this.ObjConcatURL(text)
      		} else if (type == 'stationInfo_carNumberConfirmCode') {
        		//站点信息=>生成车牌确认码
        		text.jgid = text.deptId, text.cd = text.laneName
       			this.dataObj.text = "http://xxx/xiugaichepai/index.html#/" + this.ObjConcatURL(text)
      		} else {
        		this.dataObj.text = typeof text == 'object' ? JSON.stringify(text) : text
      		}
      		this.title = title && title != '' ? title : this.$route.meta.title ? this.$route.meta.title + '二维码' : '二维码'
			console.log(this.title + "链接地址:", this.dataObj.text)

      		this.fullscreen = false
      		this.erCode = true //弹框显示
    	},
   		// 将对象拼接到url地址后面
    	ObjConcatURL(obj) {
      		if (!(typeof obj == 'object') || Object.keys(obj).length == 0) {
        		return "";
      		} else {
        		// 过滤对象中为NaN,undefined的属性
        		for (let key in obj) {
          			if (obj.hasOwnProperty(key) && (obj[key] == null || obj[key] == undefined || obj[key] == NaN || obj[key] == '')) {
            			delete obj[key]
          			}
       			}
        		// 拼接字符串到url
        		return obj ? '?' + Object.keys(obj).map(i => `${i}=${obj[i]}`).join('&') : "";
      		}
    	},
        // 复制链接
        async copyShareLink() {
            const This = this
            let clipboard = new Clipboard('.tag-copy')
            await clipboard.on('success', e => {
                This.$message.success('链接复制成功!')
                clipboard.destroy() // 释放内存
            })
            clipboard.on('error', e => {
                This.$message.error('该浏览器不支持自动复制!')  // 不支持复制  
                clipboard.destroy()  // 释放内存  
            })
        },
        // 下载二维码图片
        downloadImg() {
            let Qrcode = this.$refs.Qrcode
            this.exportLink = Qrcode.$el.currentSrc
            this.downloadFilename = this.title
        },
        // 取消按钮
        cancelBtn() {
            this.erCode = false
        },
        // 弹框是否全屏
        isFullScreen() {
            this.fullscreen = !this.fullscreen
        },
    }
}
</script>

<style scoped lang="scss">
.ebox {
    display: flex;
    align-items: center;
    justify-content: center;
}
i.fullscreen {
    position: absolute;
    right: 20px;
    top: 0px;
    padding: 10px;
    cursor: pointer;
    z-index: 9999;
}

i.fullscreen:hover {
    color: #1890FF;
}

.eboxBtn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    width: 100%;

  	a {
        flex: 1;
        display: flex;
        justify-content: center;
        margin: 5px 0 0 5px;
        color: #FFF;
        background-color: #67C23A;
        border-color: #67C23A;
        padding: 5.5px 15px;
        font-size: 14px;
        border-radius: 3px;

        &:nth-child(1) {
            background-color: #1890FF;
            border-color: #1890FF;
        }
    }
}

.footer {
    text-align: center;
    padding-top: 25px;
}
</style>
<style scoped>

>>>.el-dialog__title {
    font-weight: bold;
    color: #5a5e66;
}

>>>.el-dialog__headerbtn {
    position: absolute;
    top: 5px;
    right: 5px;
}

>>>.el-dialog--center .el-dialog__body {
    padding: 0 25px 25px;
    border-top: 1px solid #5a5e66;
}

>>>.el-button--danger {
    width: 80%;
}
</style>

如何需要扫码跳转到别的页面=>this.dataObj.text需要加

页面网址

及页面加载所

必要的参数

(参数可加密,但获取参数时需解密)



3.最终效果:

在这里插入图片描述



4、改造后

由于要使用的地方太多了,组件就只做数据接收和处理

在这里插入图片描述

【1】QRCode

<template>
  <div class="QRCode">
    <vue-qr ref="Qrcode" :text="(typeof text == 'object') ? JSON.stringify(filterObj(text)) : text"
      qid="testQrId"></vue-qr>
    <div class="QRCode-footer" v-if="isButtonDownload == true">
      <a class="tag-copy" :data-clipboard-text="(typeof text == 'object') ? JSON.stringify(filterObj(text)) : text"
        @click="copyQRCodeShareLink()">复制二维码</a>
      <a :href="exportLink" @click="downloadQRCode()" :download="downloadFilename">下载二维码</a>
    </div>
  </div>
</template>

<script>
import VueQr from 'vue-qr'// 二维码组件
import Clipboard from 'clipboard'// 复制粘贴组件

export default {
  components: { VueQr },
  props: {
    text: {//二维码内容
      type: [Number, String, Object],
      default: ''
    },
    title: {//下载图片名称
      type: String,
    },
    isButtonDownload: {
      type: [Boolean],
      default: true
    },
  },
  data() {
    return {
      logo: require('@/assets/logo.png'),
      exportLink: '',//二维码下载链接
      downloadFilename: '',//下载图片名称
    }
  },
  watch: {
    'title': function (val) {
      this.downloadFilename = val ? val : this.$route.meta.title ? this.$route.meta.title + '二维码' : '二维码'
    }
  },
  methods: {
    filterObj(obj) {
      if (!(typeof obj == 'object')) { return {}; }
      for (let key in obj) {
        if (obj.hasOwnProperty(key) && (obj[key] == null || obj[key] == undefined || obj[key] == NaN || obj[key] == '')) { delete obj[key]; }
      }
      return obj;
    },
    // 复制链接
    copyQRCodeShareLink() {
      const that = this
      let clipboard = new Clipboard('.tag-copy')
      clipboard.on('success', e => {
        that.$message.success('链接复制成功!')
        clipboard.destroy() // 释放内存
      })
      clipboard.on('error', e => {
        that.$message.warning('该浏览器不支持自动复制!')  // 不支持复制  
        clipboard.destroy()  // 释放内存  
      })
    },
    // 下载二维码图片
    downloadQRCode() {
      let Qrcode = this.$refs.Qrcode
      this.exportLink = Qrcode.$el.currentSrc
    },
  }
}
</script>

<style scoped>
@import '~@assets/less/common.less';

.QRCode {
  min-width: 200px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.QRCode-footer {
  width: 200px;
  display: flex;
  justify-content: space-evenly;

  a {
    cursor: pointer;
  }
}
</style>

【2】QRCodeModel

<template>
  <a-modal v-model="visible" :title="title" width="16%" :closable="false">
    <a-spin :spinning="confirmLoading">
      <QRCode ref="QRCode" :text="text" :title="title" />
    </a-spin>
    <template slot="footer">
      <a-button @click="handleCancel">关闭</a-button>
    </template>
  </a-modal>
</template>

<script>
import QRCode from './QRCode.vue';

export default {
  name: 'QRCodeModel',
  components: { QRCode },
  data() {
    return {
      description: '二维码弹框',

      visible: false,
      title: '二维码',
      confirmLoading: false,

      text: '',//二维码内容
    };
  },
  methods: {
    showModal(text, title) {
      const that = this
      if (!text) {
        this.$message.warning('二维码的内容不能为空!!!')
        return
      }
      that.confirmLoading = true
      that.text = (typeof text == 'object') ? that.filterObj(text) : text
      that.title = title ? title : that.$route.meta.title ? that.$route.meta.title + '二维码' : '二维码'
      that.confirmLoading = false
      that.visible = true
    },
    filterObj(obj) {
      if (!(typeof obj == 'object')) { return {}; }
      for (let key in obj) {
        if (obj.hasOwnProperty(key) && (obj[key] == null || obj[key] == undefined || obj[key] == NaN || obj[key] == '')) { delete obj[key]; }
      }
      return obj;
    },
    // 取消按钮
    handleCancel() {
      this.visible = false
    },
  },
  beforeDestroy() {
    this.record = {}
    this.fileList = []
  }
};
</script>


<style scoped>
@import '~@assets/less/common.less';

/deep/.ant-modal-content {
  min-width: 240px;
}

/deep/.ant-modal-header {
  text-align: center;
}

/deep/.ant-modal-title {
  font-weight: 600;
}
</style>

【3】全局注册

在这里插入图片描述

【4】使用:

(1)弹框

在这里插入图片描述

在这里插入图片描述

(2)内容

在这里插入图片描述



版权声明:本文为weixin_53791978原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。