feat: qrcode默认使用canvas渲染,以右键\长按存储\下载为图片

This commit is contained in:
jinye 2024-07-01 11:29:20 +08:00 committed by lmaomaoz
parent 4b3d26bbd2
commit 3ec964627b
7 changed files with 93 additions and 24 deletions

View File

@ -223,7 +223,7 @@ order: 61
"actionType": "saveAs",
"componentId": "qr-code-download",
"args": {
"name": "download.svg"
"name": "download.png"
}
}
]
@ -247,7 +247,7 @@ order: 61
| ---------------------- | ------------------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| type | `string` | `"qr-code"` | 指定为 QRCode 渲染器 |
| className | `string` | | 外层 Dom 的类名 |
| qrcodeClassName | `string` | | 二维码 SVG 的类名 |
| qrcodeClassName | `string` | | 二维码的类名 |
| codeSize | `number` | `128` | 二维码的宽高大小 |
| backgroundColor | `string` | `"#fff"` | 二维码背景色 |
| foregroundColor | `string` | `"#000"` | 二维码前景色 |

View File

@ -442,5 +442,7 @@ register('de-DE', {
'Signature.undo': 'widerrufen',
'Signature.confirm': 'bestätigen',
'Signature.cancel': 'Abbrechen',
'Signature.embedLabel': 'Klicken Sie zum Signieren'
'Signature.embedLabel': 'Klicken Sie zum Signieren',
'QRCode.tooLong':
'Der QR-Code-Wert ist zu lang, bitte setzen Sie den Text auf weniger als {{max}} Zeichen.'
});

View File

@ -426,5 +426,7 @@ register('en-US', {
'Signature.undo': 'undo',
'Signature.confirm': 'confirm',
'Signature.cancel': 'cancel',
'Signature.embedLabel': 'Click to sign'
'Signature.embedLabel': 'Click to sign',
'QRCode.tooLong':
'The QR code value is too long, please set the text to be below {{max}} characters.'
});

View File

@ -421,5 +421,6 @@ register('zh-CN', {
'Signature.undo': '撤销',
'Signature.confirm': '确认',
'Signature.cancel': '取消',
'Signature.embedLabel': '点击签名'
'Signature.embedLabel': '点击签名',
'QRCode.tooLong': '二维码值过长,请设置{{max}}个字符以下的文本'
});

File diff suppressed because one or more lines are too long

View File

@ -43,7 +43,7 @@ exports[`Renderer:qr-code QRCode render with svg 1`] = `
</div>
`;
exports[`Renderer:qr-code QRCode with background/foreground color 1`] = `
exports[`Renderer:qr-code QRCode with background/foreground color in svg 1`] = `
<div>
<div
class="cxd-Page"
@ -86,7 +86,7 @@ exports[`Renderer:qr-code QRCode with background/foreground color 1`] = `
</div>
`;
exports[`Renderer:qr-code QRCode with image 1`] = `
exports[`Renderer:qr-code QRCode with image in svg 1`] = `
<div>
<div
class="cxd-Page"

View File

@ -13,7 +13,7 @@ import {
} from 'amis-core';
import {FormItem, FormControlProps} from 'amis-core';
import {filter} from 'amis-core';
import {QRCodeSVG} from 'qrcode.react';
import QRCodeRender from 'qrcode.react';
import {BaseSchema, SchemaClassName} from '../Schema';
import {getPropValue} from 'amis-core';
import mapValues from 'lodash/mapValues';
@ -87,6 +87,11 @@ export interface QRCodeSchema extends BaseSchema {
*
*/
imageSettings?: QRCodeImageSettings;
/**
*
*/
mode?: 'canvas' | 'svg';
}
export interface QRCodeProps
@ -100,7 +105,8 @@ export default class QRCode extends React.Component<QRCodeProps, any> {
backgroundColor: '#fff',
foregroundColor: '#000',
level: 'L',
placeholder: '-'
placeholder: '-',
mode: 'canvas'
};
ref: React.RefObject<HTMLDivElement>;
@ -154,8 +160,8 @@ export default class QRCode extends React.Component<QRCodeProps, any> {
const codeSize = this.props.codeSize;
const actionType = action?.actionType as string;
if (actionType === 'saveAs') {
const fileName = args?.name || 'qr-code.svg';
if (this.ref?.current) {
if (this.props.mode === 'svg') {
const svgElement = this.ref.current.querySelector('svg');
if (svgElement) {
const contentWithSvg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="${codeSize}" width="${codeSize}" viewBox="${
@ -164,7 +170,21 @@ export default class QRCode extends React.Component<QRCodeProps, any> {
${svgElement.innerHTML}
</svg>`;
const blob = new Blob([contentWithSvg], {type: 'image/svg+xml'});
downloadBlob(blob, fileName);
downloadBlob(blob, args?.name || 'qr-code.svg');
}
} else {
const canvasElement = this.ref.current.querySelector('canvas');
if (canvasElement) {
canvasElement.toBlob(blob => {
blob &&
downloadBlob(
blob,
args?.name
? args.name.replace(/\.svg$/, '.png')
: 'qr-code.png'
);
}, 'image/png');
}
}
}
}
@ -182,6 +202,8 @@ export default class QRCode extends React.Component<QRCodeProps, any> {
level,
defaultValue,
data,
mode,
translate: __,
classPrefix: ns
} = this.props;
@ -201,10 +223,10 @@ export default class QRCode extends React.Component<QRCodeProps, any> {
) : finalValue.length > 2953 ? (
// https://github.com/zpao/qrcode.react/issues/69
<span className="text-danger">
2953
{__('QRCode.tooLong', {max: 2953})}
</span>
) : (
<QRCodeSVG
<QRCodeRender
// @ts-ignore 其实是支持的
className={qrcodeClassName}
value={finalValue}
@ -213,6 +235,7 @@ export default class QRCode extends React.Component<QRCodeProps, any> {
fgColor={foregroundColor}
level={level || 'L'}
imageSettings={this.getImageSettings()}
renderAs={mode}
/>
)}
</div>