mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-08 01:17:23 +08:00
feat: add qrcode demo (#256)
This commit is contained in:
parent
506bfc8087
commit
6c6d520dcb
@ -79,3 +79,4 @@ menus:
|
|||||||
hsDebounce: Debounce & Throttle
|
hsDebounce: Debounce & Throttle
|
||||||
hsFormDesign: Form Design
|
hsFormDesign: Form Design
|
||||||
hsBarcode: Barcode
|
hsBarcode: Barcode
|
||||||
|
hsQarcode: Qarcode
|
||||||
|
@ -79,3 +79,4 @@ menus:
|
|||||||
hsDebounce: 防抖节流
|
hsDebounce: 防抖节流
|
||||||
hsFormDesign: 表单设计器
|
hsFormDesign: 表单设计器
|
||||||
hsBarcode: 条形码
|
hsBarcode: 条形码
|
||||||
|
hsQarcode: 二维码
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"pinia": "^2.0.13",
|
"pinia": "^2.0.13",
|
||||||
|
"qrcode": "^1.5.0",
|
||||||
"qs": "^6.10.1",
|
"qs": "^6.10.1",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"responsive-storage": "^1.0.11",
|
"responsive-storage": "^1.0.11",
|
||||||
@ -93,6 +94,7 @@
|
|||||||
"@types/mockjs": "1.0.3",
|
"@types/mockjs": "1.0.3",
|
||||||
"@types/node": "14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"@types/nprogress": "0.2.0",
|
"@types/nprogress": "0.2.0",
|
||||||
|
"@types/qrcode": "^1.4.2",
|
||||||
"@types/qs": "^6.9.7",
|
"@types/qs": "^6.9.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||||
"@typescript-eslint/parser": "^5.10.2",
|
"@typescript-eslint/parser": "^5.10.2",
|
||||||
|
131
pnpm-lock.yaml
generated
131
pnpm-lock.yaml
generated
@ -26,6 +26,7 @@ specifiers:
|
|||||||
"@types/mockjs": 1.0.3
|
"@types/mockjs": 1.0.3
|
||||||
"@types/node": 14.14.14
|
"@types/node": 14.14.14
|
||||||
"@types/nprogress": 0.2.0
|
"@types/nprogress": 0.2.0
|
||||||
|
"@types/qrcode": ^1.4.2
|
||||||
"@types/qs": ^6.9.7
|
"@types/qs": ^6.9.7
|
||||||
"@typescript-eslint/eslint-plugin": ^5.10.2
|
"@typescript-eslint/eslint-plugin": ^5.10.2
|
||||||
"@typescript-eslint/parser": ^5.10.2
|
"@typescript-eslint/parser": ^5.10.2
|
||||||
@ -73,6 +74,7 @@ specifiers:
|
|||||||
postcss-scss: ^4.0.3
|
postcss-scss: ^4.0.3
|
||||||
prettier: ^2.5.1
|
prettier: ^2.5.1
|
||||||
pretty-quick: 3.1.1
|
pretty-quick: 3.1.1
|
||||||
|
qrcode: ^1.5.0
|
||||||
qs: ^6.10.1
|
qs: ^6.10.1
|
||||||
resize-observer-polyfill: ^1.5.1
|
resize-observer-polyfill: ^1.5.1
|
||||||
responsive-storage: ^1.0.11
|
responsive-storage: ^1.0.11
|
||||||
@ -137,6 +139,7 @@ dependencies:
|
|||||||
nprogress: 0.2.0
|
nprogress: 0.2.0
|
||||||
path: 0.12.7
|
path: 0.12.7
|
||||||
pinia: 2.0.13_typescript@4.6.3+vue@3.2.33
|
pinia: 2.0.13_typescript@4.6.3+vue@3.2.33
|
||||||
|
qrcode: 1.5.0
|
||||||
qs: 6.10.3
|
qs: 6.10.3
|
||||||
resize-observer-polyfill: 1.5.1
|
resize-observer-polyfill: 1.5.1
|
||||||
responsive-storage: 1.0.11_vue@3.2.33
|
responsive-storage: 1.0.11_vue@3.2.33
|
||||||
@ -174,6 +177,7 @@ devDependencies:
|
|||||||
"@types/mockjs": 1.0.3
|
"@types/mockjs": 1.0.3
|
||||||
"@types/node": 14.14.14
|
"@types/node": 14.14.14
|
||||||
"@types/nprogress": 0.2.0
|
"@types/nprogress": 0.2.0
|
||||||
|
"@types/qrcode": 1.4.2
|
||||||
"@types/qs": 6.9.7
|
"@types/qs": 6.9.7
|
||||||
"@typescript-eslint/eslint-plugin": 5.16.0_bc68a9cd5bf604202498b1a9faaf9387
|
"@typescript-eslint/eslint-plugin": 5.16.0_bc68a9cd5bf604202498b1a9faaf9387
|
||||||
"@typescript-eslint/parser": 5.16.0_eslint@8.11.0+typescript@4.6.3
|
"@typescript-eslint/parser": 5.16.0_eslint@8.11.0+typescript@4.6.3
|
||||||
@ -1493,6 +1497,15 @@ packages:
|
|||||||
}
|
}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/qrcode/1.4.2:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-7uNT9L4WQTNJejHTSTdaJhfBSCN73xtXaHFyBJ8TSwiLhe4PRuTue7Iph0s2nG9R/ifUaSnGhLUOZavlBEqDWQ==
|
||||||
|
}
|
||||||
|
dependencies:
|
||||||
|
"@types/node": 14.14.14
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/qs/6.9.7:
|
/@types/qs/6.9.7:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -2476,7 +2489,6 @@ packages:
|
|||||||
integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||||
}
|
}
|
||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-styles/3.2.1:
|
/ansi-styles/3.2.1:
|
||||||
resolution:
|
resolution:
|
||||||
@ -2495,7 +2507,6 @@ packages:
|
|||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert: 2.0.1
|
color-convert: 2.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ant-design-vue/3.2.0_vue@3.2.33:
|
/ant-design-vue/3.2.0_vue@3.2.33:
|
||||||
resolution:
|
resolution:
|
||||||
@ -2763,7 +2774,6 @@ packages:
|
|||||||
integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||||
}
|
}
|
||||||
engines: { node: ">=6" }
|
engines: { node: ">=6" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/camelcase/6.3.0:
|
/camelcase/6.3.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -2872,6 +2882,17 @@ packages:
|
|||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/cliui/6.0.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||||
|
}
|
||||||
|
dependencies:
|
||||||
|
string-width: 4.2.3
|
||||||
|
strip-ansi: 6.0.1
|
||||||
|
wrap-ansi: 6.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cliui/7.0.4:
|
/cliui/7.0.4:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -2914,7 +2935,6 @@ packages:
|
|||||||
engines: { node: ">=7.0.0" }
|
engines: { node: ">=7.0.0" }
|
||||||
dependencies:
|
dependencies:
|
||||||
color-name: 1.1.4
|
color-name: 1.1.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/color-name/1.1.3:
|
/color-name/1.1.3:
|
||||||
resolution: { integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= }
|
resolution: { integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= }
|
||||||
@ -3394,7 +3414,6 @@ packages:
|
|||||||
/decamelize/1.2.0:
|
/decamelize/1.2.0:
|
||||||
resolution: { integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= }
|
resolution: { integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= }
|
||||||
engines: { node: ">=0.10.0" }
|
engines: { node: ">=0.10.0" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/deep-is/0.1.4:
|
/deep-is/0.1.4:
|
||||||
resolution:
|
resolution:
|
||||||
@ -3427,6 +3446,13 @@ packages:
|
|||||||
engines: { node: ">=0.3.1" }
|
engines: { node: ">=0.3.1" }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/dijkstrajs/1.0.2:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==
|
||||||
|
}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/dir-glob/3.0.1:
|
/dir-glob/3.0.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -3603,7 +3629,13 @@ packages:
|
|||||||
{
|
{
|
||||||
integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||||
}
|
}
|
||||||
dev: true
|
|
||||||
|
/encode-utf8/1.0.3:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
|
||||||
|
}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/encodeurl/1.0.2:
|
/encodeurl/1.0.2:
|
||||||
resolution: { integrity: sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= }
|
resolution: { integrity: sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= }
|
||||||
@ -4435,7 +4467,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
locate-path: 5.0.0
|
locate-path: 5.0.0
|
||||||
path-exists: 4.0.0
|
path-exists: 4.0.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/find-up/5.0.0:
|
/find-up/5.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -4590,7 +4621,6 @@ packages:
|
|||||||
integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
}
|
}
|
||||||
engines: { node: 6.* || 8.* || >= 10.* }
|
engines: { node: 6.* || 8.* || >= 10.* }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/get-intrinsic/1.1.1:
|
/get-intrinsic/1.1.1:
|
||||||
resolution:
|
resolution:
|
||||||
@ -5029,7 +5059,6 @@ packages:
|
|||||||
integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||||
}
|
}
|
||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-glob/4.0.3:
|
/is-glob/4.0.3:
|
||||||
resolution:
|
resolution:
|
||||||
@ -5373,7 +5402,6 @@ packages:
|
|||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dependencies:
|
dependencies:
|
||||||
p-locate: 4.1.0
|
p-locate: 4.1.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/locate-path/6.0.0:
|
/locate-path/6.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -5937,7 +5965,6 @@ packages:
|
|||||||
engines: { node: ">=6" }
|
engines: { node: ">=6" }
|
||||||
dependencies:
|
dependencies:
|
||||||
p-try: 2.2.0
|
p-try: 2.2.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/p-limit/3.1.0:
|
/p-limit/3.1.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -5957,7 +5984,6 @@ packages:
|
|||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dependencies:
|
dependencies:
|
||||||
p-limit: 2.3.0
|
p-limit: 2.3.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/p-locate/5.0.0:
|
/p-locate/5.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -5985,7 +6011,6 @@ packages:
|
|||||||
integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||||
}
|
}
|
||||||
engines: { node: ">=6" }
|
engines: { node: ">=6" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/parent-module/1.0.1:
|
/parent-module/1.0.1:
|
||||||
resolution:
|
resolution:
|
||||||
@ -6024,7 +6049,6 @@ packages:
|
|||||||
integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||||
}
|
}
|
||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-is-absolute/1.0.1:
|
/path-is-absolute/1.0.1:
|
||||||
resolution: { integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= }
|
resolution: { integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= }
|
||||||
@ -6117,6 +6141,14 @@ packages:
|
|||||||
semver-compare: 1.0.0
|
semver-compare: 1.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/pngjs/5.0.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
|
||||||
|
}
|
||||||
|
engines: { node: ">=10.13.0" }
|
||||||
|
dev: false
|
||||||
|
|
||||||
/popmotion/11.0.3:
|
/popmotion/11.0.3:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -6679,6 +6711,20 @@ packages:
|
|||||||
engines: { node: ">=0.6.0", teleport: ">=0.2.0" }
|
engines: { node: ">=0.6.0", teleport: ">=0.2.0" }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/qrcode/1.5.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==
|
||||||
|
}
|
||||||
|
engines: { node: ">=10.13.0" }
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
dijkstrajs: 1.0.2
|
||||||
|
encode-utf8: 1.0.3
|
||||||
|
pngjs: 5.0.0
|
||||||
|
yargs: 15.4.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/qs/6.10.3:
|
/qs/6.10.3:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -6785,7 +6831,6 @@ packages:
|
|||||||
/require-directory/2.1.1:
|
/require-directory/2.1.1:
|
||||||
resolution: { integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I= }
|
resolution: { integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I= }
|
||||||
engines: { node: ">=0.10.0" }
|
engines: { node: ">=0.10.0" }
|
||||||
dev: true
|
|
||||||
|
|
||||||
/require-from-string/2.0.2:
|
/require-from-string/2.0.2:
|
||||||
resolution:
|
resolution:
|
||||||
@ -6795,6 +6840,13 @@ packages:
|
|||||||
engines: { node: ">=0.10.0" }
|
engines: { node: ">=0.10.0" }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/require-main-filename/2.0.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||||
|
}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/resize-observer-polyfill/1.5.1:
|
/resize-observer-polyfill/1.5.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -7013,6 +7065,10 @@ packages:
|
|||||||
lru-cache: 6.0.0
|
lru-cache: 6.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/set-blocking/2.0.0:
|
||||||
|
resolution: { integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc= }
|
||||||
|
dev: false
|
||||||
|
|
||||||
/shallow-equal/1.2.1:
|
/shallow-equal/1.2.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -7274,7 +7330,6 @@ packages:
|
|||||||
emoji-regex: 8.0.0
|
emoji-regex: 8.0.0
|
||||||
is-fullwidth-code-point: 3.0.0
|
is-fullwidth-code-point: 3.0.0
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/string_decoder/1.3.0:
|
/string_decoder/1.3.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -7305,7 +7360,6 @@ packages:
|
|||||||
engines: { node: ">=8" }
|
engines: { node: ">=8" }
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 5.0.1
|
ansi-regex: 5.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-final-newline/2.0.0:
|
/strip-final-newline/2.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -8119,6 +8173,10 @@ packages:
|
|||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/which-module/2.0.0:
|
||||||
|
resolution: { integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= }
|
||||||
|
dev: false
|
||||||
|
|
||||||
/which/1.3.1:
|
/which/1.3.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -8171,7 +8229,6 @@ packages:
|
|||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/wrap-ansi/7.0.0:
|
/wrap-ansi/7.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
@ -8234,6 +8291,13 @@ packages:
|
|||||||
xgplayer-subtitles: 1.0.22
|
xgplayer-subtitles: 1.0.22
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/y18n/4.0.3:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||||
|
}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/y18n/5.0.8:
|
/y18n/5.0.8:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -8268,6 +8332,17 @@ packages:
|
|||||||
engines: { node: ">= 6" }
|
engines: { node: ">= 6" }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/yargs-parser/18.1.3:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||||
|
}
|
||||||
|
engines: { node: ">=6" }
|
||||||
|
dependencies:
|
||||||
|
camelcase: 5.3.1
|
||||||
|
decamelize: 1.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/yargs-parser/20.2.9:
|
/yargs-parser/20.2.9:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -8284,6 +8359,26 @@ packages:
|
|||||||
engines: { node: ">=12" }
|
engines: { node: ">=12" }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/yargs/15.4.1:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
|
||||||
|
}
|
||||||
|
engines: { node: ">=8" }
|
||||||
|
dependencies:
|
||||||
|
cliui: 6.0.0
|
||||||
|
decamelize: 1.2.0
|
||||||
|
find-up: 4.1.0
|
||||||
|
get-caller-file: 2.0.5
|
||||||
|
require-directory: 2.1.1
|
||||||
|
require-main-filename: 2.0.0
|
||||||
|
set-blocking: 2.0.0
|
||||||
|
string-width: 4.2.3
|
||||||
|
which-module: 2.0.0
|
||||||
|
y18n: 4.0.3
|
||||||
|
yargs-parser: 18.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/yargs/17.4.0:
|
/yargs/17.4.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
|
10
src/components/ReQrcode/index.ts
Normal file
10
src/components/ReQrcode/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { App } from "vue";
|
||||||
|
import reQrcode from "./src/index";
|
||||||
|
|
||||||
|
export const ReQrcode = Object.assign(reQrcode, {
|
||||||
|
install(app: App) {
|
||||||
|
app.component(reQrcode.name, reQrcode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ReQrcode;
|
8
src/components/ReQrcode/src/index.scss
Normal file
8
src/components/ReQrcode/src/index.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.qrcode {
|
||||||
|
&--disabled {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
& > div {
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
262
src/components/ReQrcode/src/index.tsx
Normal file
262
src/components/ReQrcode/src/index.tsx
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
import {
|
||||||
|
ref,
|
||||||
|
unref,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
computed,
|
||||||
|
PropType,
|
||||||
|
defineComponent
|
||||||
|
} from "vue";
|
||||||
|
import "./index.scss";
|
||||||
|
import { isString } from "/@/utils/is";
|
||||||
|
import { cloneDeep } from "lodash-unified";
|
||||||
|
import { propTypes } from "/@/utils/propTypes";
|
||||||
|
import { IconifyIconOffline } from "../../ReIcon";
|
||||||
|
import QRCode, { QRCodeRenderersOptions } from "qrcode";
|
||||||
|
|
||||||
|
interface QrcodeLogo {
|
||||||
|
src?: string;
|
||||||
|
logoSize?: number;
|
||||||
|
bgColor?: string;
|
||||||
|
borderSize?: number;
|
||||||
|
crossOrigin?: string;
|
||||||
|
borderRadius?: number;
|
||||||
|
logoRadius?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
// img 或者 canvas,img不支持logo嵌套
|
||||||
|
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: (): QRCodeRenderersOptions => ({})
|
||||||
|
},
|
||||||
|
// 宽度
|
||||||
|
width: propTypes.number.def(200),
|
||||||
|
// logo
|
||||||
|
logo: {
|
||||||
|
type: [String, Object] as PropType<Partial<QrcodeLogo> | string>,
|
||||||
|
default: (): QrcodeLogo | string => ""
|
||||||
|
},
|
||||||
|
// 是否过期
|
||||||
|
disabled: propTypes.bool.def(false),
|
||||||
|
// 过期提示内容
|
||||||
|
disabledText: propTypes.string.def("")
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "epTableProBar",
|
||||||
|
props,
|
||||||
|
emits: ["done", "click", "disabled-click"],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const { toCanvas, toDataURL } = QRCode;
|
||||||
|
const loading = ref(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";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 用于绘制圆角
|
||||||
|
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");
|
||||||
|
};
|
||||||
|
return () => (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
v-loading={unref(loading)}
|
||||||
|
class="qrcode relative inline-block"
|
||||||
|
style={unref(wrapStyle)}
|
||||||
|
>
|
||||||
|
{props.tag === "canvas" ? (
|
||||||
|
<canvas ref={wrapRef} onClick={clickCode}></canvas>
|
||||||
|
) : (
|
||||||
|
<img ref={wrapRef} onClick={clickCode}></img>
|
||||||
|
)}
|
||||||
|
{props.disabled && (
|
||||||
|
<div
|
||||||
|
class="qrcode--disabled absolute top-0 left-0 flex w-full h-full items-center justify-center"
|
||||||
|
onClick={disabledClick}
|
||||||
|
>
|
||||||
|
<div class="absolute top-[50%] left-[50%] font-bold">
|
||||||
|
<IconifyIconOffline
|
||||||
|
class="cursor-pointer outline-none"
|
||||||
|
icon="refresh-right"
|
||||||
|
width="30"
|
||||||
|
color="var(--el-color-primary)"
|
||||||
|
/>
|
||||||
|
<div>{props.disabledText}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
@ -110,6 +110,15 @@ const ableRouter = {
|
|||||||
title: $t("menus.hsBarcode"),
|
title: $t("menus.hsBarcode"),
|
||||||
i18n: true
|
i18n: true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/able/qrcode",
|
||||||
|
name: "reQarcode",
|
||||||
|
component: () => import("/@/views/able/qrcode.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("menus.hsQarcode"),
|
||||||
|
i18n: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
113
src/views/able/qrcode.vue
Normal file
113
src/views/able/qrcode.vue
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref } from "vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import avatars from "/@/assets/avatars.jpg";
|
||||||
|
import ReQrcode from "/@/components/ReQrcode";
|
||||||
|
|
||||||
|
const qrcodeText = "vue-pure-admin";
|
||||||
|
|
||||||
|
const asyncTitle = ref("");
|
||||||
|
setTimeout(() => {
|
||||||
|
asyncTitle.value = unref(qrcodeText);
|
||||||
|
}, 3000);
|
||||||
|
const codeClick = () => {
|
||||||
|
ElMessage.info("点击事件");
|
||||||
|
};
|
||||||
|
const disabledClick = () => {
|
||||||
|
ElMessage.info("失效");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<div class="font-medium">
|
||||||
|
二维码(基于<el-link
|
||||||
|
href="https://github.com/soldair/node-qrcode"
|
||||||
|
target="_blank"
|
||||||
|
style="font-size: 16px; margin: 0 5px 4px 0"
|
||||||
|
>qrcode</el-link
|
||||||
|
>生成)
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-row :gutter="20" justify="space-between">
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">基础用法</div>
|
||||||
|
<ReQrcode :text="qrcodeText" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">img标签</div>
|
||||||
|
<ReQrcode :text="qrcodeText" tag="img" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">样式配置</div>
|
||||||
|
<ReQrcode
|
||||||
|
:text="qrcodeText"
|
||||||
|
:options="{
|
||||||
|
color: {
|
||||||
|
dark: '#55D187',
|
||||||
|
light: '#2d8cf0'
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">点击事件</div>
|
||||||
|
<ReQrcode :text="qrcodeText" @click="codeClick" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">异步内容</div>
|
||||||
|
<ReQrcode :text="asyncTitle" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">失效</div>
|
||||||
|
<ReQrcode
|
||||||
|
:text="qrcodeText"
|
||||||
|
disabled
|
||||||
|
@disabled-click="disabledClick"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">logo配置</div>
|
||||||
|
<ReQrcode :text="qrcodeText" :logo="avatars" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">logo样式</div>
|
||||||
|
<ReQrcode
|
||||||
|
:text="qrcodeText"
|
||||||
|
:logo="{
|
||||||
|
src: avatars,
|
||||||
|
logoSize: 0.2,
|
||||||
|
borderSize: 0.05,
|
||||||
|
borderRadius: 50,
|
||||||
|
bgColor: 'blue'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
|
||||||
|
<el-card shadow="hover" class="mb-10px text-center">
|
||||||
|
<div class="font-bold">大小配置</div>
|
||||||
|
<ReQrcode :text="qrcodeText" :width="100" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
x
Reference in New Issue
Block a user