一、安装插件
1、复制
npm install -g copy-to-clipboard
import copy from 'copy-to-clipboard';
2、生成二维码 & 下载
npm install -g qrcode
import QRCode from 'qrcode.react';
二、功能:生成二维码 & 下载
效果图
1、常规使用(下载图片模糊)
会有个问题:生成的二维码设置了 28px,下载的时候也是 28px,使用图片放大下载的图片就模糊。
renderer: ({ record }) => { const url = record.get('registrationUrl'); const downloadQRCode = () => { const canvas = document.getElementById('qrCodeEl'); const image = canvas.toDataURL('image/png'); const link = document.createElement('a'); link.download = 'qrcode.png'; link.href = image; link.click(); }; return ( <> {url && ( <div className={styles.registrationSource_down}> <QRCode id="qrCodeEl" value={url} size={28} level="H" includeMargin={true} style={{ border: '1px solid rgb(233, 238, 242)' }} /> <span style={{ cursor: 'pointer' }} onClick={downloadQRCode}> <img src={require('@/assets/imgs/down.png')} alt="下载二维码" /> </span> </div> )} </> ); },2、隐藏大尺寸二维码(推荐)
renderer: ({ record }) => { const url = record.get('registrationUrl'); const downloadRef = useRef<HTMLDivElement>(null); const downloadQRCode = () => { if (!downloadRef.current) return; const canvas = downloadRef.current.querySelector('canvas'); if (!canvas) return; const image = canvas.toDataURL('image/png'); const link = document.createElement('a'); link.download = 'qrcode.png'; link.href = image; link.click(); }; return ( <> {url && ( <div className={styles.registrationSource_down}> {/* 显示用小尺寸(28px) */} <QRCode value={url} size={28} level="H" includeMargin={true} style={{ border: '1px solid rgb(233, 238, 242)' }} /> {/* 隐藏的大尺寸(100px)仅用于下载 */} <div style={{ display: 'none' }} ref={downloadRef}> <QRCode value={url} size={160} level="H" includeMargin={true} /> </div> <span style={{ cursor: 'pointer' }} onClick={downloadQRCode}> <img src={require('@/assets/imgs/down.png')} alt="下载二维码" /> </span> </div> )} </> ); },三、复制
效果图
1、功能实现
renderer: ({ record }) => { const url = record.get('registrationUrl'); const handleCopy = () => { copy(url); message.success( languageConfig('tips.copySuccess', '复制成功!'), 1.5, 'top', ); }; return ( <> <span>{url}</span> <span style={{ marginLeft: '6px', cursor: 'pointer' }} onClick={handleCopy} > <img src={require('@/assets/imgs/copy.svg')} alt="" /> </span> </> ); },四、具体场景
需求:根据'输入内容'生成url(可复制),再根据url生成图片(可下载)
效果图
1、功能实现
import { Form, Modal, useDataSet, message, TextField, Button, } from 'choerodon-ui/pro'; import React, { useEffect, useRef, useState } from 'react'; import { LabelLayout } from 'choerodon-ui/pro/lib/form/enum'; import { FieldType } from 'choerodon-ui/dataset/data-set/enum'; import formatterCollections from 'hzero-front/lib/utils/intl/formatterCollections'; import { commonModelPrompt, languageConfig, prdTemCode, } from '@/language/language'; import { RegistrationRecord, RegistrationSourceCreateProps, } from '@/interface/registrationSource/main'; import { organizationId } from '@/common/config'; import { getRegistrationSourceDetail, postRegistrationSourceEdit, } from '@/api/registrationSource/main'; import '@/assets/styles/c7n.less'; import { ButtonColor, FuncType } from 'choerodon-ui/pro/lib/button/enum'; import copy from 'copy-to-clipboard'; import QRCode from 'qrcode.react'; import styles from '../list/main.less'; const CreateModel: React.FC<RegistrationSourceCreateProps> = ({ /** 控制弹框显示/隐藏 */ visible, /** 设置弹框显示/隐藏的回调函数 */ setVisible, /** 弹框关闭后回调函数 */ onSelect, infoData, }) => { const { edit, id } = infoData; const url = 'http://wwww.shuaishuaige.com/login'; /** ds */ const [, setUpdateDs] = useState(new Date().getTime()); const formDataDs = useDataSet(() => { return { autoCreate: true, fields: [ { name: 'registrationSource', type: FieldType.string, label: languageConfig( 'registrationSource.label.registrationSource', '注册来源', ), placeholder: languageConfig( 'registrationSource.label.registrationSource', '注册来源', ), maxLength: 30, required: true, }, { name: 'registrationCode', type: FieldType.string, }, { name: 'registrationUrl', type: FieldType.string, }, ], events: { update: () => { setUpdateDs(new Date().getTime()); }, }, }; }, []); /** 详情 */ const getDetail = async () => { const res = await getRegistrationSourceDetail({ id }); // console.log('详情res', res); formDataDs.current?.set({ ...res, }); }; useEffect(() => { if (visible) { formDataDs.loadData([{}]); if (edit) { getDetail(); } openModal(); } }, [visible]); /** 弹框打开 */ const openModal = () => { Modal.open({ title: edit ? languageConfig('btn.edit.registrationSource', '编辑注册来源') : languageConfig('btn.add.registrationSource', '新增注册来源'), style: { width: '400px' }, closable: true, maskClosable: true, keyboardClosable: false, onClose: () => { setVisible(false); }, children: <Box />, onOk: async () => { const validate = await formDataDs.current?.validate(true); if (!validate) return false; const { id, objectVersionNumber, registrationSource, registrationCode, registrationUrl, } = formDataDs.current?.toData() || {}; // 提交参数 const params: RegistrationRecord = { registrationSource, registrationCode, registrationUrl, registrationStatus: 'Y', tenantId: organizationId, ...(id ? { id, objectVersionNumber } : {}), }; const res = await postRegistrationSourceEdit(params); if (res.failed) { message.error(res.message, 1.5, 'top'); return false; } message.success( languageConfig('tips.operationSuccess', '操作成功!'), 1.5, 'top', ); onSelect(); }, }); }; /** 内容 */ const Box = () => { const [forceUpdate, setForceUpdate] = useState(false); useEffect(() => { const handler = () => { setForceUpdate(prev => !prev); }; formDataDs.addEventListener('update', handler); return () => formDataDs.removeEventListener('update', handler); }, []); /** 复制 */ const handleCopy = () => { const { registrationUrl } = formDataDs.current?.toData() || {}; copy(registrationUrl); message.success( languageConfig('tips.copySuccess', '复制成功!'), 1.5, 'top', ); }; /** 下载 */ const downloadRef = useRef<HTMLDivElement>(null); const downloadQRCode = () => { if (!downloadRef.current) return; const canvas = downloadRef.current.querySelector('canvas'); if (!canvas) return; const image = canvas.toDataURL('image/png'); const link = document.createElement('a'); link.download = 'qrcode.png'; link.href = image; link.click(); }; /** 生成url 和 图片 */ const handleGenerate = async () => { const { registrationSource, registrationCode } = formDataDs.current?.toData() || {}; // 1、code 不存在 if (!registrationCode) { // 调用 api const res = await postRegistrationSourceEdit({ registrationSource, tenantId: organizationId, }); if (res.failed) { message.error(res.message, 1.5, 'top'); return false; } formDataDs.loadData([res]); // url 接接 const linkUrl = `${url}?RE=${res?.registrationCode}`; formDataDs.current?.set('registrationUrl', linkUrl); } // 2、code 存在 const linkUrl = `${url}?RE=${formDataDs.current?.get( 'registrationCode', )}`; formDataDs.current?.set('registrationUrl', linkUrl); }; return ( <div className="ltc-c7n-style"> <Form dataSet={formDataDs} columns={1} labelWidth={180} labelLayout={LabelLayout.vertical} useColon={false} > <TextField name="registrationSource" onChange={val => { if (val === null) { formDataDs.current?.set('registrationUrl', ''); } }} clearButton /> <div style={{ marginTop: '4px' }}> <Button funcType={FuncType.raised} color={ButtonColor.primary} disabled={ formDataDs.current?.get('registrationSource') ? false : true } onClick={handleGenerate} > {languageConfig( 'registrationSource.btn.generateUrl', '生成url & 二维码', )} </Button> </div> {formDataDs.current?.get('registrationUrl') && ( <> <div className={styles.registrationSource_url}> <div className={styles.registrationSource_url_title}> {languageConfig( 'monthlyReports.label.registrationUrl', '注册url', )} </div> <div className={styles.registrationSource_url_text}> <span>{formDataDs.current?.get('registrationUrl')}</span> <Button funcType={FuncType.link} onClick={handleCopy}> {languageConfig('tips.copy', '复制')} </Button> </div> <div className={styles.registrationSource_url_title} style={{ marginTop: '16px' }} > {languageConfig( 'monthlyReports.label.registrationQrCode', '注册二维码', )} </div> <div className={styles.registrationSource_url_qrCode}> {/* 二维码 */} <div className={styles.registrationSource_url_qrCode_pic}> {/* 显示用小尺寸(64px) */} <QRCode value={formDataDs.current?.get('registrationUrl')} size={64} level="H" includeMargin={true} style={{ border: '1px solid rgb(233, 238, 242)' }} /> {/* 隐藏的大尺寸(100px)仅用于下载 */} <div style={{ display: 'none' }} ref={downloadRef}> <QRCode value={formDataDs.current?.get('registrationUrl')} size={160} level="H" includeMargin={true} /> </div> </div> {/* 下载 */} <Button funcType={FuncType.link} onClick={downloadQRCode}> {languageConfig('tips.qrCodeTip', '下载')} </Button> </div> </div> </> )} </Form> </div> ); }; return <></>; }; export default formatterCollections({ code: [prdTemCode, commonModelPrompt], })(CreateModel);