一、安装插件
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);