vue实现二维码生成器和解码器
vue实现二维码生成器和解码器
1.生成基本二维码:根据输入的value生成二维码。
2.可定制尺寸:通过size调整大小。
3.颜色和背景色:设置二维码颜色和背景。
4.静区(quiet zone)支持:通过quietZone调整周围的空白区域。
5.错误纠正级别:ecl参数控制容错级别。
6.渐变效果:启用线性渐变,可以自定义方向和颜色。
7.Logo嵌入:在二维码中间添加logo,可调整大小、边距、背景色和圆角。
8.错误处理:生成失败时显示错误信息。
9.响应式更新:当props变化时自动重新生成二维码。
10.视图框调整:根据静区计算viewBox,确保正确显示。
效果图:

step1: 添加依赖 npm install qrcode @types/qrcode
step2:核心组件 实现二维码
C:\Users\wangrusheng\PycharmProjects\untitled3\src\views\QrCode.vue
<template><!-- SVG 容器 --><svgv-if="!error":viewBox="viewBox":width="size":height="size"><!-- 背景 --><rect:x="-quietZone":y="-quietZone":width="size + quietZone * 2":height="size + quietZone * 2":fill="backgroundColor"/><!-- 渐变定义 --><defs v-if="enableLinearGradient"><linearGradientid="grad":x1="gradientDirection[0]":y1="gradientDirection[1]":x2="gradientDirection[2]":y2="gradientDirection[3]"><stop offset="0" :stop-color="linearGradient[0]" stop-opacity="1"/><stop offset="1" :stop-color="linearGradient[1]" stop-opacity="1"/></linearGradient></defs><!-- 二维码路径 --><path:d="path"stroke-linecap="butt":stroke="enableLinearGradient ? 'url(#grad)' : color":stroke-width="cellSize"/><!-- Logo 容器 --><svgv-if="logo":x="(size - logoSize - logoMargin * 2) / 2":y="(size - logoSize - logoMargin * 2) / 2"><!-- Logo 背景 --><rect:width="logoSize + logoMargin * 2":height="logoSize + logoMargin * 2":fill="logoBackgroundColor":rx="logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius":ry="logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius"/><!-- Logo 图片 --><image:x="logoMargin":y="logoMargin":width="logoSize":height="logoSize":href="logo"preserveAspectRatio="xMidYMid slice":rx="logoBorderRadius":ry="logoBorderRadius"/></svg></svg><!-- 错误显示 --><div v-if="error" class="error">{{ error.message }}</div>
</template><script setup lang="ts">
import { ref, watchEffect, computed } from 'vue'
import QRCode from 'qrcode'// Props 定义
const props = defineProps({value: { type: String, default: 'this is a QR code' },size: { type: Number, default: 100 },color: { type: String, default: 'black' },backgroundColor: { type: String, default: 'white' },logo: { type: String, default: undefined },logoSize: { type: Number, default: 100 * 0.2 }, // 默认基于 size 计算logoBackgroundColor: { type: String, default: 'transparent' },logoMargin: { type: Number, default: 2 },logoBorderRadius: { type: Number, default: 0 },quietZone: { type: Number, default: 0 },enableLinearGradient: { type: Boolean, default: false },gradientDirection: {type: Array as () => string[],default: () => ['0%', '0%', '100%', '100%']},linearGradient: {type: Array as () => string[],default: () => ['rgb(255,0,0)', 'rgb(0,255,255)']},ecl: { type: String as () => 'L'|'M'|'Q'|'H', default: 'M' }
})// 响应式数据
const path = ref('')
const cellSize = ref(0)
const error = ref<Error | null>(null)// 生成二维码矩阵
const genMatrix = (value: string, errorCorrectionLevel: string): boolean[][] => {const arr = Array.prototype.slice.call(QRCode.create(value, { errorCorrectionLevel }).modules.data, 0)const sqrt = Math.sqrt(arr.length)return arr.reduce((rows: boolean[][], key: boolean, index: number) => {(index % sqrt === 0) ? rows.push([key]) : rows[rows.length - 1].push(key)return rows}, [])
}// 转换矩阵为 SVG 路径
const transformMatrixIntoPath = (matrix: boolean[][], size: number) => {const cellSize = size / matrix.lengthlet path = ''matrix.forEach((row, i) => {let needDraw = falserow.forEach((column, j) => {if (column) {if (!needDraw) {path += `M${cellSize * j} ${cellSize / 2 + cellSize * i} `needDraw = true}if (needDraw && j === matrix.length - 1) {path += `L${cellSize * (j + 1)} ${cellSize / 2 + cellSize * i} `}} else {if (needDraw) {path += `L${cellSize * j} ${cellSize / 2 + cellSize * i} `needDraw = false}}})})return { cellSize, path }
}// 计算 viewBox
const viewBox = computed(() => [-props.quietZone,-props.quietZone,props.size + props.quietZone * 2,props.size + props.quietZone * 2
].join(' '))// 监听 props 变化
watchEffect(() => {try {const matrix = genMatrix(props.value, props.ecl)const result = transformMatrixIntoPath(matrix, props.size)path.value = result.pathcellSize.value = result.cellSizeerror.value = null} catch (err) {error.value = err instanceof Error ? err : new Error('QR Code generation failed')}
})
</script><style scoped>
.error {color: red;border: 1px solid red;padding: 1rem;
}
</style>
step3: 调用二维码组件
C:\Users\wangrusheng\PycharmProjects\untitled3\src\views\ImgCode.vue
<template><QrCode:value="qrCodeValue":size="200"color="#333"logo="/logo.png":logo-size="40"logo-background-color="white":enable-linear-gradient="true"/>
</template><script setup>
import QrCode from './QrCode.vue'
import { ref } from 'vue'
// 图片资源存放在 C:\Users\wangrusheng\PycharmProjects\untitled3\public\logo.png
// JSON.stringify() 是 JavaScript 中用于将对象或值转换为 JSON 格式字符串的核心方法,
//value="你们好,这里是二维码识别器,很高兴认识你们"
const qrCodeValue = ref(JSON.stringify({"data": [{"case_id": 3,"category_id": 4,"title": "as","description": "ad","price": 4500.0,"client_id": 5,"lawyer_id": 6,"status": "pending","created_at": "2025-03-21T06:11:59","updated_at": "2025-03-21T06:11:59","category_name": "af"},{"case_id": 8,"category_id": 8,"title": "bs","description": "bd","price": 6000.0,"client_id": 5,"lawyer_id": 6,"status": "in_progress","created_at": "2025-03-21T06:11:59","updated_at": "2025-03-21T06:11:59","category_name": "bf"}]
}))
</script>
step4:路由
C:\Users\wangrusheng\PycharmProjects\untitled3\src\router\index.js
import ImgCode from '../views/ImgCode.vue'
{ path: '/imgcode', name: 'imgcode', component: ImgCode },C:\Users\wangrusheng\PycharmProjects\untitled3\src\App.vue
<router-link to="/imgcode" active-class="active-link">二维码</router-link>
///我是分割线
解码部分
step101:安装依赖 pip install pyzbar Pillow,你去网站上,随便找个二维码生成器,然后将生成的二维码保存本地
step102:解析C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\hello.py
from pyzbar.pyzbar import decode
from PIL import Image# 二维码图片路径 C:\Users\wangrusheng\Downloads
old_file = r'C:\Users\wangrusheng\Downloads\logoz.png'try:# 打开图片文件with Image.open(old_file) as img:# 解析二维码decoded_objects = decode(img)if not decoded_objects:print("未检测到二维码内容。")else:for obj in decoded_objects:# 解码数据(假设内容为UTF-8文本)data = obj.data.decode('utf-8')print("解析结果:", data)except FileNotFoundError:print(f"错误:文件 '{old_file}' 不存在。")
except Exception as e:print(f"解析时发生错误: {str(e)}")
step103:运行
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python hello.py
解析结果: 能不能点点赞 点点关注,我谢谢大家
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1>
end
相关文章:
vue实现二维码生成器和解码器
vue实现二维码生成器和解码器 1.生成基本二维码:根据输入的value生成二维码。 2.可定制尺寸:通过size调整大小。 3.颜色和背景色:设置二维码颜色和背景。 4.静区(quiet zone)支持:通过quietZone调整周围的…...
TypeScript 的 interface 接口
TypeScript 的 interface 接口 简介 interface 是对象的模板,可以看作是一种类型约定,中文译为“接口”。使用了某个模板的对象,就拥有了指定的类型结构。 interface Person {firstName: string;lastName: string;age: number;} 上面示例中…...
c#和form实现WebSocket在线聊天室
c#和form实现WebSocket在线聊天室 功能点 后端程序 (Program.cs)1.WebSocket 聊天服务器核心功能a.管理客户端连接(ConnectionManager 类)b.支持公聊消息广播(所有用户可见)c.支持私聊消息(通过 用户ID 格式指…...
量子代理签名:量子时代的数字授权革命
1. 量子代理签名的定义与核心原理 量子代理签名(Quantum Proxy Signature, QPS)是经典代理签名在量子信息领域的延伸,允许原始签名者(Original Signer)授权给代理签名者(Proxy Signer)代为签署文…...
「Unity3D」TextMeshPro中的TMP_InputField,用来实现输入框的几个小问题
第一,正确设置Scrollbar。 设置Scrollbar之后,不能设置Text Component的Font Size为Auto Size,否则Scrollbar无法正确计算显示。 那么,要想自动适配字体大小,可以让Placeholder中的Font Size设置为Auto,这…...
Docker 介绍 · 安装详细教程
为什么选择 Docker? ✅ 环境一致性 – 告别“在我机器上能跑”的问题,确保开发、测试、生产环境一致。 ✅ 高效轻量 – 秒级启动,资源占用远低于传统虚拟机。 ✅ 跨平台支持 – 可在任何支持 Docker 的环境中运行,包括云服务器、…...
vulnhub:sunset decoy
靶机下载地址https://www.vulnhub.com/entry/sunset-decoy,505/ 渗透过程 简单信息收集 nmap 192.168.56.0/24 -Pn # 确定靶机ip:192.168.56.121 nmap 192.168.56.121 -A -T4 # 得到开放端口22,80 在80端口得到save.zip,需要密码解压。 john破解压缩…...
方案精读:71页制造企业一体化ERP系统项目实施方案【附全文阅读】
今天聊聊制造企业 ERP 系统项目实施方案。 某钾肥企业在发展中面临信息化难题,像物资编码不规范、业务手工化、财务业务脱节等 。为此,打造 “流程驱动,业务整合” 的一体化 ERP 管理平台很关键。它涵盖采购、销售、生产、运营流程,实现供应链、预算、资金、财务整…...
MATLAB遇到内部问题,需要关闭,Crash Decoding : Disabled - No sandbox or build area path
1.故障界面 MATLAB运行时突然中断,停止运行。故障界面如图: MATLAB Log File: C:\Users\wei\AppData\Local\Temp\matlab_crash_dump.21720-1 ------------------------------------------------ MATLAB Log File -----------------------------------…...
【Redis】Redis C++使用
一、Redis的自定义网络协议 1.1 为什么可以编写出一个自定义的Redis客户端 为什么我们可以编写出一个自定义的Redis客户端?因为Redis公开了自己的自定义协议。而对于一些其他软件的客户端,我们无法编写出一个自定义的Redis客户端,因为他们没…...
每日一题(小白)暴力娱乐篇19
样例: 6 1 1 4 5 1 4 输出: 56 66 52 44 54 64 分析题意可以得知,就是接收一串数字,将数字按照下标每次向右移动一位(末尾循环到第一位),每次移动玩计算一下下标和数字的乘积且累加。 ①接收…...
25级总分413数学一142专业124东南大学820考研经验电子信息通信工程,真题,大纲,参考书。
我是南京理工大学的本科生,25 考研一战东大,政治 69,英一 78,数一 142,专业课(820)124,总分 413。我从 3 月正式开始备考,专业课跟着无线电论坛jenny 老师进行学习&#…...
一个基于Django的进销存管理系统Demo实现
第一步:创建 Django 项目 bash 复制 django-admin startproject inventory_system cd inventory_system python manage.py startapp erp 第二步:定义数据模型(models.py) python 复制 from django.db import models from d…...
【数据结构_6上篇】有关链表的oj题
import java.util.*;/* public class ListNode {int val;ListNode next null;ListNode(int val) {this.val val;} }*/ public class Partition {public ListNode partition(ListNode pHead, int x) {// write code here//1.首先要判断链表是否为空的情况if(pHead null){retu…...
【QT】QWidget 概述与核心属性(API)
🌈 个人主页:Zfox_ 🔥 系列专栏:Qt 目录 一:🔥 控件概述 🦋 控件体系的发展阶段 二:🔥 QWidget 核心属性 🦋 核心属性概览🦋 用件可用(…...
微服务篇——SpringCloud
服务注册 Spring Cloud5大组件有哪些? 服务注册和发现是什么意思?Spring Cloud如何实现服务注册发现? nacos与eureka的区别 负载均衡 如何实现负载均衡? Ribbon负载均衡的策略有哪些? 如何自定义负载均衡的策略&…...
如何使用PyCharm自动化测试
如何使用PyCharm自动化测试 1.打开PyCharm右击文件,点击新建项目 按照如图配置,然后点击创建 2.创建好后,点击文件,然后点击设置 按照如图步骤,查看selenium和webdriver-manager是否存在 3.以上都完成后按照如图创…...
记一次某网络安全比赛三阶段webserver应急响应解题过程
0X01 任务说明 0X02 靶机介绍 Webserver(Web服务器)是一种软件或硬件设备,用于接收、处理并响应来自客户端(如浏览器)的HTTP请求,提供网页、图片、视频等静态或动态内容,是互联网基础设施的核心…...
c# 新建不重名的唯一文件夹
在源文件夹内创建唯一目标文件夹 string newFolder GetUniqueFolderName(sourceFolder); Directory.CreateDirectory(newFolder); /// <summary>/// 生成唯一文件夹名称(格式:新建文件夹、新建文件夹1、新建文件夹2...)…...
复现QGIS-MCP教程
由于Claude国内下载不了尝试使用Cursor 下载安装Cursor Cursor - The AI Code Editor 本示例安装的是0.46版本 UV安装 简介 安装 安装成功 配置环境变量 验证 下载代码 git clone gitgithub.com:jjsantos01/qgis_mcp.git QGIS插件安装 文件拷贝 您需要将 qgis_mcp_plu…...
SQL:JOIN 完全指南:从基础到实战应用
JOIN 是 SQL 中最重要也最常用的操作之一,它允许我们从多个表中获取关联数据。本文将全面解析 SQL 中的各种 JOIN 类型,包括 INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN 以及 CROSS JOIN,并通过实际示例展示它们的应用场景。 一、JOIN 基础概念 1.1 什么是 JOIN JOIN…...
docker部署certimateSSL证书管理自动续签
开源certimate项目地址:https://github.com/usual2970/certimate 官方文档地址:https://docs.certimate.me/docs/introduction 与certbot对比 维度CertbotCertimate安装方式通过包管理器(如apt/yum)安装支持二进制文件、Docker…...
R语言——直方图
参考资料:学习R 如果我们要研究一个连续变量的分布,直方图是最佳的选择。 1、base绘图 在base中可以使用hist函数绘制直方图,与plot函数一样,它没有data参数,须把数据框置于with中。 data(obama_vs_mccain,package&q…...
第4节:Python编程基础 - Python语法快速回顾
1. Python简介与环境配置 Python是一种高级、解释型、通用的编程语言,由Guido van Rossum于1991年首次发布。 它以简洁明了的语法和强大的功能而闻名,广泛应用于Web开发、数据分析、人工智能、科学计算等领域。 1.1 Python的特点 简单易学:…...
十四、C++速通秘籍—函数式编程
目录 上一章节: 一、引言 一、函数式编程基础 三、Lambda 表达式 作用: Lambda 表达式捕获值的方式: 注意: 四、函数对象 函数对象与普通函数对比: 五、函数适配器 1、适配普通函数 2、适配 Lambda 表达式 …...
蓝桥杯 2025 C++组 省 B 题解
可分解的正整数 算法:思维 因为可以有负数 所以除了1以外的任何数都可以构造 当这个数为x构造方法为 -(x-1) -(x-2) -(x-3) ....-1 0 1...x-3 x-2 x-1 x 除了x,x以前的数都会被负数抵消 #include <bits/stdc.h> #define ll long long ll a…...
如何让老电脑运行快些(极限榨干老电脑硬件)
要让老电脑运行更快,可以通过增加虚拟内存、优化系统设置和硬件升级等方法实现。以下是具体建议: 1. 增加虚拟内存(适合硬盘空间大的老电脑) 虚拟内存(页面文件)是硬盘上的一部分空间,用于扩展…...
博物馆小程序怎么做?从0到1打造数字化文化窗口
博物馆小程序怎么做?从0到1打造数字化文化窗口 一、行业痛点:传统博物馆的数字化困局 在数字化浪潮下,传统博物馆普遍面临三大挑战: 客流受限:线下接待能力有限,难以触达更广泛人群 互动单一…...
信息学奥赛一本通 1498:Roadblocks | 洛谷 P2865 [USACO06NOV] Roadblocks G
【题目链接】 ybt 1498:Roadblocks 洛谷 P2865 [USACO06NOV] Roadblocks G 【题目考点】 1. 图论:严格次短路径 严格次短路的路径长度必须大于最短路的路径长度。 非严格次短路的路径长度大于等于最短路的路径长度。 【解题思路】 每个交叉路口是一…...
1.5-APP的架构\微信小程序的架构
1.5-APP的架构\微信小程序的架构 APP的三种开发架构: 原生态APP类型 APP-开发架构-原生态-IDEA 演示:remusic项目源码 NP管理器: http://normalplayer.top/ HttpCanary:https://github.com/mingww64/HttpCanary-SSL-Magisk 安全影…...
