import React, { useState, useRef } from ‘react‘; import { QrcodeOutlined } from ‘@ant-design/icons‘; import ‘@ant-design/compatible/assets/index.css‘; import { Modal, Button, message } from ‘antd‘; import { useObserver } from ‘mobx-react‘; import { useHistory, useLocation } from ‘react-router-dom‘; // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore import QrCode from ‘qrcode-reader‘; import jsQR from ‘jsqr‘; import ajax from ‘@/lib/axios‘; import { Wrapper, SuccessWrapper, UploadImgWrapper } from ‘./link-qrcode-style‘; interface IProps { merchantId: string; branchName: string; merchantName: string; personInCharge: string; } const LinkQrCode = (props: IProps) => { const qr = new QrCode(); const [showConfirmModal, setShowConfirmModal] = useState<boolean>(false); const [showSuccessModal, setShowSuccessModal] = useState<boolean>(false); const [showUploadModal, setShowUploadModal] = useState<boolean>(false); const [uploadButtonLoading, setUploadButtonLoading] = useState<boolean>(false); const [confirmButtonLoading, setConfirmButtonLoading] = useState<boolean>(false); const [qrCodeUrl, setQrCodeUrl] = useState<string>(‘‘); const [qrDecode, setQrDecode] = useState<string>(‘‘); const [uploadImgUrl, setUploadImgUrl] = useState<string>(‘‘); const [uploadImgFile, setUploadImgFile] = useState<object>({}); const history = useHistory(); const location = useLocation(); const fileInputRef = useRef<HTMLInputElement>(null); // const ua = navigator.userAgent.toLowerCase(); // const isIos = ua.indexOf(‘iphone‘) !== -1 || ua.indexOf(‘ipad‘) !== -1; const backToListPage = () => { const to = `${location.pathname}${location.search}`; history.push(to); }; const getFileUrl = (file: object) => { if (file === undefined) return; let url = null; if ((window as any).createObjectURL != undefined) { // basic url = (window as any).createObjectURL(file); } else if (window.URL != undefined) { // mozilla(firefox) url = window.URL.createObjectURL(file); } else if (window.webkitURL != undefined) { // webkit or chrome url = window.webkitURL.createObjectURL(file); } return url; }; const getQrCode = () => { console.log(‘beibei111‘, uploadImgFile); qr.decode(uploadImgUrl); qr.callback = async function(error: any, resCode: any) { if (error) { Modal.error({ content: error, }); return; } const decodeArr = resCode.result.split(‘/‘); const cutQrDecode = decodeArr[decodeArr.length - 1]; console.log(‘beibei1113333‘, resCode.result, cutQrDecode, uploadImgFile); setQrDecode(cutQrDecode); // 请求后端接口进行解析 try { const { data: { data }, } = await ajax.get(`/qrcode/validate/${cutQrDecode}`); console.log(‘beibei 是否有效‘, data); setUploadButtonLoading(false); setShowUploadModal(false); if (data) { setShowConfirmModal(true); } else { Modal.error({ content: "Sorry, we can‘t process this picture, please make sure you use a clear picture of valid QR code.", onOk() { const to = `${location.pathname}${location.search}`; history.push(to); }, }); } } catch (e) { message.error(e.message); } }; }; const handleLinkButton = (e: React.MouseEvent) => { e.preventDefault(); if (!!fileInputRef) { (fileInputRef as any).current.click(); } }; const handleFileChange = (e: any) => { const files = e.target.files; if (files[0] !== undefined) { const fr = new FileReader(); fr.readAsDataURL(files[0]); fr.addEventListener(‘load‘, () => { setUploadImgUrl(fr.result as string); setUploadImgFile(files[0]); setShowUploadModal(true); // qrCodeUploadedHandler(fr.result as string); drawImg(files[0]); }); } else { setUploadImgUrl(‘‘); setUploadImgFile({}); } }; const drawImg = (file: any) => { createImageBitmap(file).then(bmp => { const canvas = document.createElement(‘canvas‘); const width: number = bmp.width; const height: number = bmp.height; canvas.width = bmp.width; canvas.height = bmp.height; const ctx = canvas.getContext(‘2d‘) as any; ctx.drawImage(bmp, 0, 0); const qrCodeImageFormat = ctx.getImageData(0, 0, bmp.width, bmp.height); const qrDecoded = jsQR(qrCodeImageFormat.data, qrCodeImageFormat.width, qrCodeImageFormat.height); alert(qrDecoded.data); console.log(‘beibeicccmmmmm‘, qrCodeImageFormat, qrDecoded); }); }; const qrCodeUploadedHandler = (fileImageUrl: string) => { const img = new Image(); // img.src = fileImageUrl; img.onload = () => { const canvas = document.createElement(‘canvas‘); const originWidth = img.width; const originHeight = img.height; // const maxWidth = 1600; // const maxHeight = 1200; // let targetWidth = originWidth; // let targetHeight = originHeight; // if (originWidth > maxWidth || originHeight > maxHeight) { // if (originWidth / originHeight > maxWidth / maxHeight) { // // 更宽,按照宽度限定尺寸 // targetWidth = maxWidth; // targetHeight = Math.round(maxWidth * (originHeight / originWidth)); // } else { // targetHeight = maxHeight; // targetWidth = Math.round(maxHeight * (originWidth / originHeight)); // } // }; // canvas对图片进行缩放 canvas.width = originWidth; canvas.height = originHeight; const context = canvas.getContext(‘2d‘) as any; // 清除画布 // context.clearRect(0, 0, targetWidth, targetHeight); // 图片压缩 context.drawImage(img, 0, 0); const imageData = context.getImageData(0, 0, canvas.width, canvas.height); const code = jsQR(imageData.data, imageData.width, imageData.height); console.log(‘beibeiccc222‘, imageData, code); canvas.remove(); }; img.onerror = () => console.error(‘Upload file of image format please.‘); img.src = fileImageUrl; }; const handleUploadButton = (e: React.MouseEvent) => { e.preventDefault(); setUploadButtonLoading(true); getQrCode(); }; const handleConfirmLink = async (e: React.MouseEvent) => { e.preventDefault(); setConfirmButtonLoading(true); try { const { data: { data }, } = await ajax.post(‘/qrcode/bind‘, { qrcode: qrDecode, bindObjectId: props.merchantId }); if (data.length > 0) { setQrCodeUrl(data[0]); setConfirmButtonLoading(false); setShowConfirmModal(false); setShowSuccessModal(true); } } catch (e) { message.error(e.message); } }; const handleConfirmModalCancel = (e: React.MouseEvent) => { e.preventDefault(); setShowConfirmModal(false); backToListPage(); }; const handleSuccessModalCancel = (e: React.MouseEvent) => { e.preventDefault(); setShowSuccessModal(false); backToListPage(); }; return useObserver(() => ( <> <div> <Button onClick={handleLinkButton} style={{ width: ‘100%‘, marginTop: 5 }} type="default" size="small"> <QrcodeOutlined /> Link QR code </Button> <input type="file" name="cover" accept="image/*" ref={fileInputRef} style={{ width: 0, height: 0 }} onChange={handleFileChange} /> </div> <Modal destroyOnClose={true} title="Confirm Information" visible={showConfirmModal} style={{ top: 20 }} width={‘50%‘} maskClosable={false} footer={[ <Button type="primary" key="confirm" loading={confirmButtonLoading} htmlType="button" onClick={handleConfirmLink}> Confirm </Button>, <Button key="cancel" htmlType="button" onClick={handleConfirmModalCancel}> Cancel </Button>, ]} onCancel={handleConfirmModalCancel}> <Wrapper> <p> {/* eslint-disable-next-line react/no-unescaped-entities */} You‘re linking the QR code you scaned to the following merchant. Please check the merchant information throughly. </p> <div className="confirm-information"> <div className="confirm-information-item"> <span>Merchant ID:</span> <p>{props.merchantId}</p> </div> <div className="confirm-information-item"> <span>Branch Name:</span> <p>{props.branchName}</p> </div> <div className="confirm-information-item"> <span>Merchant Name:</span> <p>{props.merchantName}</p> </div> <div className="confirm-information-item"> <span>Person in Charge:</span> <p>{props.personInCharge}</p> </div> </div> </Wrapper> </Modal> <Modal destroyOnClose={true} visible={showSuccessModal} style={{ top: 20 }} width={‘50%‘} maskClosable={false} footer={null} onCancel={handleSuccessModalCancel}> <SuccessWrapper> <p className="top-tip">QR code has been successfully linked!</p> <div className="branch-name"> <span>Branch Name:</span> <p>{props.branchName}</p> </div> <div className="qr-code"> <span>QR Code:</span> <img src={qrCodeUrl} alt="图片加载失败" /> </div> </SuccessWrapper> </Modal> <Modal destroyOnClose={true} visible={showUploadModal} style={{ top: 20, textAlign: ‘center‘ }} width={‘50%‘} maskClosable={false} closable={false} footer={null}> <UploadImgWrapper> <img src={uploadImgUrl} style={{ maxWidth: ‘400px‘ }} /> </UploadImgWrapper> <Button type="primary" key="confirm" loading={uploadButtonLoading} size="large" htmlType="button" style={{ margin: ‘20px‘ }} onClick={handleUploadButton}> UPLOAD </Button> </Modal> </> )); }; export default LinkQrCode;
原文:https://www.cnblogs.com/chenbeibei520/p/12526522.html