复制 & 生成二维码

发布于:2025-06-30 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、安装插件

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);


网站公告

今日签到

点亮在社区的每一天
去签到