vue实现二维码天生器息争码器

[复制链接]
发表于 2025-9-25 14:34:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
vue实现二维码天生器息争码器
2.可定制尺寸:通过size调整巨细。
4.静区(quiet zone)支持:通过quietZone调整附近的空缺地域。
5.错误纠正级别:ecl参数控制容错级别。
6.渐变效果:启用线性渐变,可以自界说方向和颜色。
8.错误处置处罚:天生失败时体现错误信息。
10.视图框调整:根据静区计算viewBox,确保精确体现。
效果图:

step1: 添加依赖 npm install qrcode @types/qrcode
step2:核心组件 实现二维码
C:\Users\wangrusheng\PycharmProjects\untitled3\src\views\QrCode.vue
  1. <template>
  2.   <!-- SVG 容器 -->
  3.   <svg
  4.     v-if="!error"
  5.     :viewBox="viewBox"
  6.     :width="size"
  7.     :height="size"
  8.   >
  9.     <!-- 背景 -->
  10.     <rect
  11.       :x="-quietZone"
  12.       :y="-quietZone"
  13.       :width="size + quietZone * 2"
  14.       :height="size + quietZone * 2"
  15.       :fill="backgroundColor"
  16.     />
  17.     <!-- 渐变定义 -->
  18.     <defs v-if="enableLinearGradient">
  19.       <linearGradient
  20.         id="grad"
  21.         :x1="gradientDirection[0]"
  22.         :y1="gradientDirection[1]"
  23.         :x2="gradientDirection[2]"
  24.         :y2="gradientDirection[3]"
  25.       >
  26.         <stop offset="0" :stop-color="linearGradient[0]" stop-opacity="1"/>
  27.         <stop offset="1" :stop-color="linearGradient[1]" stop-opacity="1"/>
  28.       </linearGradient>
  29.     </defs>
  30.     <path
  31.       :d="path"
  32.       stroke-linecap="butt"
  33.       :stroke="enableLinearGradient ? 'url(#grad)' : color"
  34.       :stroke-width="cellSize"
  35.     />
  36.     <!-- Logo 容器 -->
  37.     <svg
  38.       v-if="logo"
  39.       :x="(size - logoSize - logoMargin * 2) / 2"
  40.       :y="(size - logoSize - logoMargin * 2) / 2"
  41.     >
  42.       <!-- Logo 背景 -->
  43.       <rect
  44.         :width="logoSize + logoMargin * 2"
  45.         :height="logoSize + logoMargin * 2"
  46.         :fill="logoBackgroundColor"
  47.         :rx="logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius"
  48.         :ry="logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius"
  49.       />
  50.       <!-- Logo 图片 -->
  51.       <image
  52.         :x="logoMargin"
  53.         :y="logoMargin"
  54.         :width="logoSize"
  55.         :height="logoSize"
  56.         :href="logo"
  57.         preserveAspectRatio="xMidYMid slice"
  58.         :rx="logoBorderRadius"
  59.         :ry="logoBorderRadius"
  60.       />
  61.     </svg>
  62.   </svg>
  63.   <!-- 错误显示 -->
  64.   <div v-if="error" class="error">
  65.     {{ error.message }}
  66.   </div>
  67. </template>
  68. <script setup lang="ts">
  69. import { ref, watchEffect, computed } from 'vue'
  70. import QRCode from 'qrcode'
  71. // Props 定义
  72. const props = defineProps({
  73.   value: { type: String, default: 'this is a QR code' },
  74.   size: { type: Number, default: 100 },
  75.   color: { type: String, default: 'black' },
  76.   backgroundColor: { type: String, default: 'white' },
  77.   logo: { type: String, default: undefined },
  78.   logoSize: { type: Number, default: 100 * 0.2 }, // 默认基于 size 计算
  79.   logoBackgroundColor: { type: String, default: 'transparent' },
  80.   logoMargin: { type: Number, default: 2 },
  81.   logoBorderRadius: { type: Number, default: 0 },
  82.   quietZone: { type: Number, default: 0 },
  83.   enableLinearGradient: { type: Boolean, default: false },
  84.   gradientDirection: {
  85.     type: Array as () => string[],
  86.     default: () => ['0%', '0%', '100%', '100%']
  87.   },
  88.   linearGradient: {
  89.     type: Array as () => string[],
  90.     default: () => ['rgb(255,0,0)', 'rgb(0,255,255)']
  91.   },
  92.   ecl: { type: String as () => 'L'|'M'|'Q'|'H', default: 'M' }
  93. })
  94. // 响应式数据
  95. const path = ref('')
  96. const cellSize = ref(0)
  97. const error = ref<Error | null>(null)
  98. const genMatrix = (value: string, errorCorrectionLevel: string): boolean[][] => {
  99.   const arr = Array.prototype.slice.call(
  100.     QRCode.create(value, { errorCorrectionLevel }).modules.data, 0
  101.   )
  102.   const sqrt = Math.sqrt(arr.length)
  103.   return arr.reduce((rows: boolean[][], key: boolean, index: number) => {
  104.     (index % sqrt === 0) ? rows.push([key]) : rows[rows.length - 1].push(key)
  105.     return rows
  106.   }, [])
  107. }
  108. // 转换矩阵为 SVG 路径
  109. const transformMatrixIntoPath = (matrix: boolean[][], size: number) => {
  110.   const cellSize = size / matrix.length
  111.   let path = ''
  112.   matrix.forEach((row, i) => {
  113.     let needDraw = false
  114.     row.forEach((column, j) => {
  115.       if (column) {
  116.         if (!needDraw) {
  117.           path += `M${cellSize * j} ${cellSize / 2 + cellSize * i} `
  118.           needDraw = true
  119.         }
  120.         if (needDraw && j === matrix.length - 1) {
  121.           path += `L${cellSize * (j + 1)} ${cellSize / 2 + cellSize * i} `
  122.         }
  123.       } else {
  124.         if (needDraw) {
  125.           path += `L${cellSize * j} ${cellSize / 2 + cellSize * i} `
  126.           needDraw = false
  127.         }
  128.       }
  129.     })
  130.   })
  131.   return { cellSize, path }
  132. }
  133. // 计算 viewBox
  134. const viewBox = computed(() => [
  135.   -props.quietZone,
  136.   -props.quietZone,
  137.   props.size + props.quietZone * 2,
  138.   props.size + props.quietZone * 2
  139. ].join(' '))
  140. // 监听 props 变化
  141. watchEffect(() => {
  142.   try {
  143.     const matrix = genMatrix(props.value, props.ecl)
  144.     const result = transformMatrixIntoPath(matrix, props.size)
  145.     path.value = result.path
  146.     cellSize.value = result.cellSize
  147.     error.value = null
  148.   } catch (err) {
  149.     error.value = err instanceof Error ? err : new Error('QR Code generation failed')
  150.   }
  151. })
  152. </script>
  153. <style scoped>
  154. .error {
  155.   color: red;
  156.   border: 1px solid red;
  157.   padding: 1rem;
  158. }
  159. </style>
  160. C:\Users\wangrusheng\PycharmProjects\untitled3\src\views\ImgCode.vue
  161. [code]<template>
  162.   <QrCode
  163.     :value="qrCodeValue"
  164.     :size="200"
  165.     color="#333"
  166.     logo="/logo.png"
  167.     :logo-size="40"
  168.     logo-background-color="white"
  169.     :enable-linear-gradient="true"
  170.   />
  171. </template>
  172. <script setup>
  173. import QrCode from './QrCode.vue'
  174. import { ref } from 'vue'
  175. // 图片资源存放在 C:\Users\wangrusheng\PycharmProjects\untitled3\public\logo.png
  176. // JSON.stringify() 是 JavaScript 中用于将对象或值转换为 JSON 格式字符串的核心方法,
  177. const qrCodeValue = ref(JSON.stringify({
  178.   "data": [
  179.     {
  180.       "case_id": 3,
  181.       "category_id": 4,
  182.       "title": "as",
  183.       "description": "ad",
  184.       "price": 4500.0,
  185.       "client_id": 5,
  186.       "lawyer_id": 6,
  187.       "status": "pending",
  188.       "created_at": "2025-03-21T06:11:59",
  189.       "updated_at": "2025-03-21T06:11:59",
  190.       "category_name": "af"
  191.     },
  192.     {
  193.       "case_id": 8,
  194.       "category_id": 8,
  195.       "title": "bs",
  196.       "description": "bd",
  197.       "price": 6000.0,
  198.       "client_id": 5,
  199.       "lawyer_id": 6,
  200.       "status": "in_progress",
  201.       "created_at": "2025-03-21T06:11:59",
  202.       "updated_at": "2025-03-21T06:11:59",
  203.       "category_name": "bf"
  204.     }
  205.   ]
  206. }))
  207. </script>
复制代码
step4:路由
  1. C:\Users\wangrusheng\PycharmProjects\untitled3\src\router\index.js
  2. import ImgCode from '../views/ImgCode.vue'
  3. { path: '/imgcode', name: 'imgcode', component: ImgCode },
  4. C:\Users\wangrusheng\PycharmProjects\untitled3\src\App.vue
复制代码
///我是分割线
解码部门
step102:剖析C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\hello.py
  1. from pyzbar.pyzbar import decode
  2. from PIL import Image
  3. old_file = r'C:\Users\wangrusheng\Downloads\logoz.png'
  4. try:
  5.     # 打开图片文件
  6.     with Image.open(old_file) as img:
  7.         decoded_objects = decode(img)
  8.         if not decoded_objects:
  9.             print("未检测到二维码内容。")
  10.         else:
  11.             for obj in decoded_objects:
  12.                 # 解码数据(假设内容为UTF-8文本)
  13.                 data = obj.data.decode('utf-8')
  14.                 print("解析结果:", data)
  15. except FileNotFoundError:
  16.     print(f"错误:文件 '{old_file}' 不存在。")
  17. except Exception as e:
  18.     print(f"解析时发生错误: {str(e)}")
复制代码
step103:运行
  1. (.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python hello.py
  2. 解析结果: 能不能点点赞  点点关注,我谢谢大家
  3. (.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1>
复制代码
end
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表