feat: Add Qrcode component and add qrcode demo

This commit is contained in:
陈凯龙 2022-01-27 09:51:03 +08:00
parent d3fbd3a06c
commit 535a31b35e
11 changed files with 583 additions and 38 deletions

View File

@ -38,6 +38,7 @@
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"pinia": "^2.0.9",
"qrcode": "^1.5.0",
"qs": "^6.10.3",
"vue": "3.2.26",
"vue-i18n": "9.1.9",
@ -55,6 +56,7 @@
"@types/lodash-es": "^4.17.5",
"@types/node": "^17.0.10",
"@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.4.2",
"@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",

View File

@ -11,6 +11,7 @@ specifiers:
'@types/lodash-es': ^4.17.5
'@types/node': ^17.0.10
'@types/nprogress': ^0.2.0
'@types/qrcode': ^1.4.2
'@types/qs': ^6.9.7
'@typescript-eslint/eslint-plugin': ^5.10.0
'@typescript-eslint/parser': ^5.10.0
@ -43,6 +44,7 @@ specifiers:
postcss-less: ^6.0.0
prettier: ^2.5.1
pretty-quick: ^3.1.3
qrcode: ^1.5.0
qs: ^6.10.3
rimraf: ^3.0.2
stylelint: ^14.2.0
@ -82,6 +84,7 @@ dependencies:
mockjs: registry.npmmirror.com/mockjs/1.1.0
nprogress: registry.npmmirror.com/nprogress/0.2.0
pinia: registry.npmmirror.com/pinia/2.0.9_typescript@4.5.5+vue@3.2.26
qrcode: registry.npmmirror.com/qrcode/1.5.0
qs: registry.npmmirror.com/qs/6.10.3
vue: registry.npmmirror.com/vue/3.2.26
vue-i18n: registry.npmmirror.com/vue-i18n/9.1.9_vue@3.2.26
@ -99,6 +102,7 @@ devDependencies:
'@types/lodash-es': registry.npmmirror.com/@types/lodash-es/4.17.5
'@types/node': registry.npmmirror.com/@types/node/17.0.10
'@types/nprogress': registry.npmmirror.com/@types/nprogress/0.2.0
'@types/qrcode': registry.npmmirror.com/@types/qrcode/1.4.2
'@types/qs': registry.npmmirror.com/@types/qs/6.9.7
'@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.10.0_706fb07ce74b1db611f19a02ad2ce784
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.10.0_eslint@8.7.0+typescript@4.5.5
@ -469,7 +473,6 @@ packages:
name: ansi-regex
version: 5.0.1
engines: { node: '>=8' }
dev: true
registry.nlark.com/ansi-regex/6.0.1:
resolution:
@ -483,20 +486,6 @@ packages:
engines: { node: '>=12' }
dev: true
registry.nlark.com/ansi-styles/4.3.0:
resolution:
{
integrity: sha1-7dgDYornHATIWuegkG7a00tkiTc=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz
}
name: ansi-styles
version: 4.3.0
engines: { node: '>=8' }
dependencies:
color-convert: registry.npmmirror.com/color-convert/2.0.1
dev: true
registry.nlark.com/anymatch/3.1.2:
resolution:
{
@ -1038,6 +1027,21 @@ packages:
version: 2.2.1
dev: true
registry.nlark.com/cliui/6.0.0:
resolution:
{
integrity: sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/cliui/download/cliui-6.0.0.tgz
}
name: cliui
version: 6.0.0
dependencies:
string-width: registry.npmmirror.com/string-width/4.2.3
strip-ansi: registry.npmmirror.com/strip-ansi/6.0.1
wrap-ansi: registry.nlark.com/wrap-ansi/6.2.0
dev: false
registry.nlark.com/cliui/7.0.4:
resolution:
{
@ -1114,7 +1118,6 @@ packages:
}
name: color-name
version: 1.1.4
dev: true
registry.nlark.com/compare-func/2.0.0:
resolution:
@ -1498,6 +1501,17 @@ packages:
engines: { node: '>=0.3.1' }
dev: true
registry.nlark.com/dijkstrajs/1.0.2:
resolution:
{
integrity: sha1-LkjA07glRir+datK1egpyOzjYlc=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/dijkstrajs/download/dijkstrajs-1.0.2.tgz
}
name: dijkstrajs
version: 1.0.2
dev: false
registry.nlark.com/dir-glob/3.0.1:
resolution:
{
@ -2343,7 +2357,6 @@ packages:
name: get-caller-file
version: 2.0.5
engines: { node: 6.* || 8.* || >= 10.* }
dev: true
registry.nlark.com/get-intrinsic/1.1.1:
resolution:
@ -3051,7 +3064,6 @@ packages:
name: is-fullwidth-code-point
version: 3.0.0
engines: { node: '>=8' }
dev: true
registry.nlark.com/is-fullwidth-code-point/4.0.0:
resolution:
@ -3511,7 +3523,6 @@ packages:
engines: { node: '>=8' }
dependencies:
p-locate: registry.nlark.com/p-locate/4.1.0
dev: true
registry.nlark.com/locate-path/6.0.0:
resolution:
@ -4163,7 +4174,6 @@ packages:
engines: { node: '>=6' }
dependencies:
p-try: registry.npmmirror.com/p-try/2.2.0
dev: true
registry.nlark.com/p-limit/3.1.0:
resolution:
@ -4191,7 +4201,6 @@ packages:
engines: { node: '>=8' }
dependencies:
p-limit: registry.nlark.com/p-limit/2.3.0
dev: true
registry.nlark.com/p-locate/5.0.0:
resolution:
@ -4307,7 +4316,6 @@ packages:
name: path-exists
version: 4.0.0
engines: { node: '>=8' }
dev: true
registry.nlark.com/path-is-absolute/1.0.1:
resolution:
@ -4381,6 +4389,18 @@ packages:
dev: true
optional: true
registry.nlark.com/pngjs/5.0.0:
resolution:
{
integrity: sha1-553SshV2f9nARWHAEjbflgvOf7s=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/pngjs/download/pngjs-5.0.0.tgz
}
name: pngjs
version: 5.0.0
engines: { node: '>=10.13.0' }
dev: false
registry.nlark.com/posix-character-classes/0.1.1:
resolution:
{
@ -4906,6 +4926,17 @@ packages:
engines: { node: '>=0.10.0' }
dev: true
registry.nlark.com/require-main-filename/2.0.0:
resolution:
{
integrity: sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/require-main-filename/download/require-main-filename-2.0.0.tgz
}
name: require-main-filename
version: 2.0.0
dev: false
registry.nlark.com/resolve-dir/1.0.1:
resolution:
{
@ -5166,6 +5197,17 @@ packages:
upper-case-first: registry.nlark.com/upper-case-first/2.0.2
dev: true
registry.nlark.com/set-blocking/2.0.0:
resolution:
{
integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/set-blocking/download/set-blocking-2.0.0.tgz
}
name: set-blocking
version: 2.0.0
dev: false
registry.nlark.com/set-value/2.0.1:
resolution:
{
@ -6107,6 +6149,17 @@ packages:
version: 5.0.0
dev: true
registry.nlark.com/which-module/2.0.0:
resolution:
{
integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/which-module/download/which-module-2.0.0.tgz
}
name: which-module
version: 2.0.0
dev: false
registry.nlark.com/which/1.3.1:
resolution:
{
@ -6179,7 +6232,6 @@ packages:
ansi-styles: registry.npmmirror.com/ansi-styles/4.3.0
string-width: registry.npmmirror.com/string-width/4.2.3
strip-ansi: registry.npmmirror.com/strip-ansi/6.0.1
dev: true
registry.nlark.com/wrap-ansi/7.0.0:
resolution:
@ -6224,6 +6276,17 @@ packages:
typedarray-to-buffer: registry.nlark.com/typedarray-to-buffer/3.1.5
dev: true
registry.nlark.com/y18n/4.0.3:
resolution:
{
integrity: sha1-tfJZyCzW4zaSHv17/Yv1YN6e7t8=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.nlark.com/y18n/download/y18n-4.0.3.tgz
}
name: y18n
version: 4.0.3
dev: false
registry.nlark.com/y18n/5.0.8:
resolution:
{
@ -7680,6 +7743,19 @@ packages:
version: 4.0.0
dev: true
registry.npmmirror.com/@types/qrcode/1.4.2:
resolution:
{
integrity: sha512-7uNT9L4WQTNJejHTSTdaJhfBSCN73xtXaHFyBJ8TSwiLhe4PRuTue7Iph0s2nG9R/ifUaSnGhLUOZavlBEqDWQ==,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.npmmirror.com/@types/qrcode/download/@types/qrcode-1.4.2.tgz
}
name: '@types/qrcode'
version: 1.4.2
dependencies:
'@types/node': registry.npmmirror.com/@types/node/17.0.10
dev: true
registry.npmmirror.com/@types/qs/6.9.7:
resolution:
{
@ -8592,7 +8668,6 @@ packages:
engines: { node: '>=8' }
dependencies:
color-convert: registry.npmmirror.com/color-convert/2.0.1
dev: true
registry.npmmirror.com/ansi-styles/6.1.0:
resolution:
@ -8797,7 +8872,6 @@ packages:
name: camelcase
version: 5.3.1
engines: { node: '>=6' }
dev: true
registry.npmmirror.com/camelcase/6.2.1:
resolution:
@ -8867,7 +8941,7 @@ packages:
version: 3.0.0
engines: { node: '>=8' }
dependencies:
ansi-styles: registry.nlark.com/ansi-styles/4.3.0
ansi-styles: registry.npmmirror.com/ansi-styles/4.3.0
supports-color: registry.npmmirror.com/supports-color/7.2.0
dev: true
@ -8987,7 +9061,6 @@ packages:
engines: { node: '>=7.0.0' }
dependencies:
color-name: registry.nlark.com/color-name/1.1.4
dev: true
registry.npmmirror.com/colord/2.9.2:
resolution:
@ -9339,7 +9412,6 @@ packages:
name: decamelize
version: 1.2.0
engines: { node: '>=0.10.0' }
dev: true
registry.npmmirror.com/declass/0.0.1:
resolution:
@ -9483,7 +9555,6 @@ packages:
}
name: emoji-regex
version: 8.0.0
dev: true
registry.npmmirror.com/emoji-regex/9.2.2:
resolution:
@ -9496,6 +9567,17 @@ packages:
version: 9.2.2
dev: true
registry.npmmirror.com/encode-utf8/1.0.3:
resolution:
{
integrity: sha1-8w/dMdoH+1lvKBvrL2sCeFGZTNo=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.npmmirror.com/encode-utf8/download/encode-utf8-1.0.3.tgz
}
name: encode-utf8
version: 1.0.3
dev: false
registry.npmmirror.com/error-ex/1.3.2:
resolution:
{
@ -10247,7 +10329,6 @@ packages:
dependencies:
locate-path: registry.nlark.com/locate-path/5.0.0
path-exists: registry.nlark.com/path-exists/4.0.0
dev: true
registry.npmmirror.com/find-up/5.0.0:
resolution:
@ -11310,7 +11391,6 @@ packages:
name: p-try
version: 2.2.0
engines: { node: '>=6' }
dev: true
registry.npmmirror.com/parent-module/1.0.1:
resolution:
@ -11609,6 +11689,24 @@ packages:
version: 2.0.0
dev: true
registry.npmmirror.com/qrcode/1.5.0:
resolution:
{
integrity: sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.npmmirror.com/qrcode/download/qrcode-1.5.0.tgz
}
name: qrcode
version: 1.5.0
engines: { node: '>=10.13.0' }
hasBin: true
dependencies:
dijkstrajs: registry.nlark.com/dijkstrajs/1.0.2
encode-utf8: registry.npmmirror.com/encode-utf8/1.0.3
pngjs: registry.nlark.com/pngjs/5.0.0
yargs: registry.npmmirror.com/yargs/15.4.1
dev: false
registry.npmmirror.com/qs/6.10.3:
resolution:
{
@ -11661,7 +11759,6 @@ packages:
name: require-directory
version: 2.1.1
engines: { node: '>=0.10.0' }
dev: true
registry.npmmirror.com/resolve-global/1.0.0:
resolution:
@ -11885,7 +11982,6 @@ packages:
emoji-regex: registry.npmmirror.com/emoji-regex/8.0.0
is-fullwidth-code-point: registry.nlark.com/is-fullwidth-code-point/3.0.0
strip-ansi: registry.npmmirror.com/strip-ansi/6.0.1
dev: true
registry.npmmirror.com/string-width/5.0.1:
resolution:
@ -11957,7 +12053,6 @@ packages:
engines: { node: '>=8' }
dependencies:
ansi-regex: registry.nlark.com/ansi-regex/5.0.1
dev: true
registry.npmmirror.com/strip-ansi/7.0.1:
resolution:
@ -12972,6 +13067,21 @@ packages:
engines: { node: '>= 6' }
dev: true
registry.npmmirror.com/yargs-parser/18.1.3:
resolution:
{
integrity: sha1-vmjEl1xrKr9GkjawyHA2L6sJp7A=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.npmmirror.com/yargs-parser/download/yargs-parser-18.1.3.tgz
}
name: yargs-parser
version: 18.1.3
engines: { node: '>=6' }
dependencies:
camelcase: registry.npmmirror.com/camelcase/5.3.1
decamelize: registry.npmmirror.com/decamelize/1.2.0
dev: false
registry.npmmirror.com/yargs-parser/20.2.9:
resolution:
{
@ -12996,6 +13106,30 @@ packages:
engines: { node: '>=12' }
dev: true
registry.npmmirror.com/yargs/15.4.1:
resolution:
{
integrity: sha1-DYehbeAa7p2L7Cv7909nhRcw9Pg=,
registry: https://registry.npm.taobao.org/,
tarball: https://registry.npmmirror.com/yargs/download/yargs-15.4.1.tgz
}
name: yargs
version: 15.4.1
engines: { node: '>=8' }
dependencies:
cliui: registry.nlark.com/cliui/6.0.0
decamelize: registry.npmmirror.com/decamelize/1.2.0
find-up: registry.npmmirror.com/find-up/4.1.0
get-caller-file: registry.nlark.com/get-caller-file/2.0.5
require-directory: registry.npmmirror.com/require-directory/2.1.1
require-main-filename: registry.nlark.com/require-main-filename/2.0.0
set-blocking: registry.nlark.com/set-blocking/2.0.0
string-width: registry.npmmirror.com/string-width/4.2.3
which-module: registry.nlark.com/which-module/2.0.0
y18n: registry.nlark.com/y18n/4.0.3
yargs-parser: registry.npmmirror.com/yargs-parser/18.1.3
dev: false
registry.npmmirror.com/yargs/17.3.1:
resolution:
{

View File

@ -0,0 +1,3 @@
import Qrcode from './src/Qrcode.vue'
export { Qrcode }

View File

@ -0,0 +1,251 @@
<script setup lang="ts">
import { PropType, nextTick, ref, watch, computed, unref } from 'vue'
import QRCode from 'qrcode'
import { QRCodeRenderersOptions } from 'qrcode'
import { cloneDeep } from 'lodash-es'
import { propTypes } from '@/utils/propTypes'
import { useDesign } from '@/hooks/web/useDesign'
import { isString } from '@/utils/is'
const props = defineProps({
// img canvas,imglogo
tag: propTypes.string.validate((v: string) => ['canvas', 'img'].includes(v)).def('canvas'),
//
text: {
type: [String, Array] as PropType<string | Recordable[]>,
default: null
},
// qrcode.js
options: {
type: Object as PropType<QRCodeRenderersOptions>,
default: () => ({})
},
//
width: propTypes.number.def(200),
// logo
logo: {
type: [String, Object] as PropType<Partial<QrcodeLogo> | string>,
default: ''
},
//
disabled: propTypes.bool.def(false),
//
disabledText: propTypes.string.def('')
})
const emit = defineEmits(['done', 'click', 'disabled-click'])
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('qrcode')
const { toCanvas, toDataURL } = QRCode
const loading = ref<boolean>(true)
const wrapRef = ref<Nullable<HTMLCanvasElement | HTMLImageElement>>(null)
const renderText = computed(() => String(props.text))
const wrapStyle = computed(() => {
return {
width: props.width + 'px',
height: props.width + 'px'
}
})
const initQrcode = async () => {
await nextTick()
const options = cloneDeep(props.options || {})
if (props.tag === 'canvas') {
//
options.errorCorrectionLevel =
options.errorCorrectionLevel || getErrorCorrectionLevel(unref(renderText))
const _width: number = await getOriginWidth(unref(renderText), options)
options.scale = props.width === 0 ? undefined : (props.width / _width) * 4
const canvasRef: HTMLCanvasElement = await toCanvas(
unref(wrapRef) as HTMLCanvasElement,
unref(renderText),
options
)
if (props.logo) {
const url = await createLogoCode(canvasRef)
emit('done', url)
loading.value = false
} else {
emit('done', canvasRef.toDataURL())
loading.value = false
}
} else {
const url = await toDataURL(renderText.value, {
errorCorrectionLevel: 'H',
width: props.width,
...options
})
;(unref(wrapRef) as HTMLImageElement).src = url
emit('done', url)
loading.value = false
}
}
watch(
() => renderText.value,
(val) => {
if (!val) return
initQrcode()
},
{
deep: true,
immediate: true
}
)
const createLogoCode = (canvasRef: HTMLCanvasElement) => {
const canvasWidth = canvasRef.width
const logoOptions: QrcodeLogo = Object.assign(
{
logoSize: 0.15,
bgColor: '#ffffff',
borderSize: 0.05,
crossOrigin: 'anonymous',
borderRadius: 8,
logoRadius: 0
},
isString(props.logo) ? {} : props.logo
)
const {
logoSize = 0.15,
bgColor = '#ffffff',
borderSize = 0.05,
crossOrigin = 'anonymous',
borderRadius = 8,
logoRadius = 0
} = logoOptions
const logoSrc = isString(props.logo) ? props.logo : props.logo.src
const logoWidth = canvasWidth * logoSize
const logoXY = (canvasWidth * (1 - logoSize)) / 2
const logoBgWidth = canvasWidth * (logoSize + borderSize)
const logoBgXY = (canvasWidth * (1 - logoSize - borderSize)) / 2
const ctx = canvasRef.getContext('2d')
if (!ctx) return
// logo
canvasRoundRect(ctx)(logoBgXY, logoBgXY, logoBgWidth, logoBgWidth, borderRadius)
ctx.fillStyle = bgColor
ctx.fill()
// logo
const image = new Image()
if (crossOrigin || logoRadius) {
image.setAttribute('crossOrigin', crossOrigin)
}
;(image as any).src = logoSrc
// 使image
const drawLogoWithImage = (image: HTMLImageElement) => {
ctx.drawImage(image, logoXY, logoXY, logoWidth, logoWidth)
}
// 使canvas
const drawLogoWithCanvas = (image: HTMLImageElement) => {
const canvasImage = document.createElement('canvas')
canvasImage.width = logoXY + logoWidth
canvasImage.height = logoXY + logoWidth
const imageCanvas = canvasImage.getContext('2d')
if (!imageCanvas || !ctx) return
imageCanvas.drawImage(image, logoXY, logoXY, logoWidth, logoWidth)
canvasRoundRect(ctx)(logoXY, logoXY, logoWidth, logoWidth, logoRadius)
if (!ctx) return
const fillStyle = ctx.createPattern(canvasImage, 'no-repeat')
if (fillStyle) {
ctx.fillStyle = fillStyle
ctx.fill()
}
}
// logo canvas
return new Promise((resolve: any) => {
image.onload = () => {
logoRadius ? drawLogoWithCanvas(image) : drawLogoWithImage(image)
resolve(canvasRef.toDataURL())
}
})
}
// QrCode便QrCode
const getOriginWidth = async (content: string, options: QRCodeRenderersOptions) => {
const _canvas = document.createElement('canvas')
await toCanvas(_canvas, content, options)
return _canvas.width
}
// QrCode
const getErrorCorrectionLevel = (content: string) => {
if (content.length > 36) {
return 'M'
} else if (content.length > 16) {
return 'Q'
} else {
return 'H'
}
}
// copy
const canvasRoundRect = (ctx: CanvasRenderingContext2D) => {
return (x: number, y: number, w: number, h: number, r: number) => {
const minSize = Math.min(w, h)
if (r > minSize / 2) {
r = minSize / 2
}
ctx.beginPath()
ctx.moveTo(x + r, y)
ctx.arcTo(x + w, y, x + w, y + h, r)
ctx.arcTo(x + w, y + h, x, y + h, r)
ctx.arcTo(x, y + h, x, y, r)
ctx.arcTo(x, y, x + w, y, r)
ctx.closePath()
return ctx
}
}
const clickCode = () => {
emit('click')
}
const disabledClick = () => {
emit('disabled-click')
}
</script>
<template>
<div v-loading="loading" :class="[prefixCls, 'relative inline-block']" :style="wrapStyle">
<component :is="tag" ref="wrapRef" @click="clickCode" />
<div
v-if="disabled"
:class="`${prefixCls}--disabled`"
class="absolute top-0 left-0 flex w-full h-full items-center justify-center"
@click="disabledClick"
>
<div class="absolute top-[50%] left-[50%] font-bold">
<Icon icon="ep:refresh-right" :size="30" color="var(--el-color-primary)" />
<div>{{ disabledText }}</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
@prefix-cls: ~'@{namespace}-qrcode';
.@{prefix-cls} {
&--disabled {
background: rgba(255, 255, 255, 0.95);
& > div {
transform: translate(-50%, -50%);
}
}
}
</style>

View File

@ -90,7 +90,8 @@ export default {
icon: 'Icon',
echart: 'Echart',
countTo: 'Count to',
watermark: 'Watermark'
watermark: 'Watermark',
qrcode: 'Qrcode'
},
analysis: {
newUser: 'New user',
@ -231,5 +232,18 @@ export default {
createdWatermark: 'Created watermark',
clearWatermark: 'Clear watermark',
resetWatermark: 'Reset watermark'
},
qrcodeDemo: {
qrcode: 'Qrcode',
qrcodeDes: 'Secondary packaging based on qrcode',
basicUsage: 'Basic usage',
imgTag: 'Img tag',
style: 'Style config',
click: 'Click event',
asynchronousContent: 'Asynchronous content',
invalid: 'Invalid',
logoConfig: 'Logo config',
logoStyle: 'Logo style',
size: 'size config'
}
}

View File

@ -90,7 +90,8 @@ export default {
icon: '图标',
echart: '图表',
countTo: '数字动画',
watermark: '水印'
watermark: '水印',
qrcode: '二维码'
},
analysis: {
newUser: '新增用户',
@ -230,5 +231,18 @@ export default {
createdWatermark: '创建水印',
clearWatermark: '清除水印',
resetWatermark: '重置水印'
},
qrcodeDemo: {
qrcode: '二维码',
qrcodeDes: '基于 qrcode 二次封装',
basicUsage: '基础用法',
imgTag: 'img标签',
style: '样式配置',
click: '点击事件',
asynchronousContent: '异步内容',
invalid: '失效',
logoConfig: 'logo配置',
logoStyle: 'logo样式',
size: '大小配置'
}
}

View File

@ -127,6 +127,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
meta: {
title: t('router.watermark')
}
},
{
path: 'qrcode',
component: () => import('@/views/Components/Qrcode.vue'),
name: 'Qrcode',
meta: {
title: t('router.qrcode')
}
}
]
},

View File

@ -0,0 +1,108 @@
<script setup lang="ts">
import { Qrcode } from '@/components/Qrcode'
import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { computed, ref, unref } from 'vue'
import { useAppStore } from '@/store/modules/app'
import { ElRow, ElCard, ElCol, ElMessage } from 'element-plus'
// @ts-ignore
import logoImg from '@/assets/imgs/logo.png'
const appStore = useAppStore()
const { t } = useI18n()
const title = computed(() => appStore.getTitle)
const asyncTitle = ref('')
setTimeout(() => {
asyncTitle.value = unref(title)
}, 3000)
const codeClick = () => {
ElMessage.info(t('qrcodeDemo.click'))
}
const disabledClick = () => {
ElMessage.info(t('qrcodeDemo.invalid'))
}
</script>
<template>
<ContentWrap :title="t('qrcodeDemo.qrcode')" :message="t('qrcodeDemo.qrcodeDes')">
<ElRow :gutter="20" justify="space-between">
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.basicUsage') }}</div>
<Qrcode :text="title" />
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.imgTag') }}</div>
<Qrcode :text="title" tag="img" />
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.style') }}</div>
<Qrcode
:text="title"
:options="{
color: {
dark: '#55D187',
light: '#2d8cf0'
}
}"
/>
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.click') }}</div>
<Qrcode :text="title" @click="codeClick" />
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.asynchronousContent') }}</div>
<Qrcode :text="asyncTitle" />
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.invalid') }}</div>
<Qrcode :text="title" disabled @disabled-click="disabledClick" />
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.logoConfig') }}</div>
<Qrcode :text="title" :logo="logoImg" />
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.logoStyle') }}</div>
<Qrcode
:text="title"
:logo="{
src: logoImg,
logoSize: 0.2,
borderSize: 0.05,
borderRadius: 50,
bgColor: 'blue'
}"
/>
</ElCard>
</ElCol>
<ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
<ElCard shadow="hover" class="mb-10px text-center">
<div class="font-bold mb-10px">{{ t('qrcodeDemo.size') }}</div>
<Qrcode :text="title" :width="250" />
</ElCard>
</ElCol>
</ElRow>
</ContentWrap>
</template>

View File

@ -27,7 +27,8 @@
"@intlify/vite-plugin-vue-i18n/client",
"vite/client",
"element-plus/global",
"@types/intro.js"
"@types/intro.js",
"@types/qrcode"
],
"typeRoots": ["./node_modules/@types/", "./types"]
},

9
types/componentType/qrcode.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
declare interface QrcodeLogo {
src?: string
logoSize?: number
bgColor?: string
borderSize?: number
crossOrigin?: string
borderRadius?: number
logoRadius?: number
}

View File

@ -133,7 +133,8 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
'qs',
'echarts',
'echarts-wordcloud',
'intro.js'
'intro.js',
'qrcode'
]
}
}