设计一个赞赏组件

前言

本源讲述开源代码 react-approval, 这个前端组件可以用于 PC 网页中,以便于人们通过选择相应的金额赞赏给网页中文章的作者。当然,你也可以直接用微信的赞赏码功能,效果是一样的。

一个赞赏组件包含哪些元素

最起码包含 赞赏金额选择组、确认赞赏按钮、微信二维码组件、赞赏留言框、发起赞赏组件。

赞赏金额选择组

设计图如

赞赏金额选择组

组件名为:ApproveChoices

import React, { useState, useEffect, useRef } from 'react';
import css from './ApproveChoices.module.css';
import cx from 'classnames';
import Button from '@mui/material/Button';
import Divider from '@mui/material/Divider';
import Box from '@mui/material/Box';
import { Wxpay } from 'components/icons/';
import BInput from 'components/frameui/input/';

export default ({ amountList, onPay }) => {
  const [selectedAmountIndex, setSelectedAmountIndex] = useState(-1);
  const remarkRef = useRef(null);

  const handleAmountClick = (item, index, e) => {
    setSelectedAmountIndex(index);
  };

  const handlePay = (e) => {
    if (selectedAmountIndex < 0) return;
    const item = amountList[selectedAmountIndex];
    // console.log('amount is %s', item.value);
    if (onPay) {
      onPay(
	{ item: [item, selectedAmountIndex], remark: remarkRef.current.value },
	e
      );
    }
  };

  const isSelected = (i) => selectedAmountIndex === i;

  return (
    <div className={css.paymentContainer}>
      <div className={css.Dialoguser}>
	<span className={css.RewardUserAvatar}>
	  <img
	    src="//qiniu.imesu.co/rm/defaults/fly-bird.png"
	    className={css.RewardAvatar}
	    alt="当前用户"
	  />
	</span>
	学问鸽
      </div>
      <div className={css.tagLine}>真诚赞赏,手留余香</div>
      <Box sx={{ my: 3 }}>
	<div className={css.amountOptionContainer}>
	  {amountList.map((item, i) => (
	    <button
	      data-index={i}
	      data-id={item.id}
	      key={item.value + i}
	      data-btn-name={`amount-btn--${item.label}`}
	      className={cx(css.amountOption, {
		[css.isActive]: isSelected(i),
	      })}
	      onClick={(e) => handleAmountClick(null, i, e)}
	    >
	      {item.label}
	    </button>
	  ))}
	</div>
      </Box>
      {selectedAmountIndex > -1 ? (
	<Box sx={{ my: 2 }}>
	  <BInput placeholder="留言" ref={remarkRef} />
	</Box>
      ) : null}
      {selectedAmountIndex > -1 ? (
	<React.Fragment>
	  <Divider />
	  <Box sx={{ my: 2 }}>
	    <div className="u-row is-fullfill u-t14">
	      <span style={{ color: '#999' }}>支付方式</span>
	      <div className="u-row is-center">
		<Wxpay width="14px" height="16px" className="u-mr4" />
		<span>微信支付</span>
	      </div>
	    </div>
	  </Box>

	  <Button
	    variant="contained"
	    className="u-wfull u-mt24"
	    sx={{ height: 44, fontSize: 16 }}
	    onClick={handlePay}
	  >
	    确认支付
	  </Button>
	</React.Fragment>
      ) : null}
    </div>
  );
};

确认赞赏按钮

设计图如

确认赞赏按钮

确认支付按钮组件已经包含在组件 ApproveChoices 中。

<Button
  variant="contained"
  className="u-wfull u-mt24"
  sx={{ height: 44, fontSize: 16 }}
  onClick={handlePay}
>
  确认支付
</Button>

微信二维码组件

设计图如

确认赞赏按钮

组件名是 WxpayWrap

import React, { useState, useEffect } from 'react';
import { useWxpayQrcode, useWxPayOrderState } from 'shared/hooks/wxpay';
import Wxpay from './Wxpay';

const WxpayWrap = ({ orderNo, maxWaitTime = 3 * 60000, onPaySuccess }) => {
  const wxpayQrcode = useWxpayQrcode(orderNo);
  useWxPayOrderState(orderNo, maxWaitTime, onPaySuccess);

  return (
    <div data-order-no={orderNo}>
      <Wxpay wxpayQrcode={wxpayQrcode} />
    </div>
  );
};

export default WxpayWrap;

赞赏留言框

设计图如

确认赞赏按钮

如果使用者有选择对应的金额,则展示留言框。留言框组件已包含在上述组件 ApproveChoices 中。

{selectedAmountIndex > -1 ? (
  <Box sx={{ my: 2 }}>
    <BInput placeholder="留言" ref={remarkRef} />
  </Box>
) : null}

发起赞赏组件(提示文本和按钮)

设计图如

确认赞赏按钮

组件名为 ApprovalEntry

import React from 'react';
import css from './ApprovalEntry.module.css';

const ApprovalEntry = ({ inviteText, onClick }) => {
  return (
    <div className={css.Reward}>
      <div>
	<div className={css.tagline}>真诚赞赏,手留余香</div>
	<button className={css.rewardBtn} onClick={onClick}>
	  赞赏
	</button>
      </div>
      <div className={css.RewardcountZero}>
	{/* 还没有人赞赏,快来当第一个赞赏的人吧!*/}
	{inviteText}
      </div>
    </div>
  );
};

export default ApprovalEntry;

如何使用这个组件

挂载 sdk

挂载 React 和 ReactDOM 和 react-approval

由于打包的时候没有将 React 和 ReactDOM 作为 externals 外部库加以排除。故而在使用时无需引用 React 和 ReactDOM 库。

在 react 框架中使用组件 react-approval

只需要将 window.ReactApproval 挂载到(.mount()) html 元素节点即可。这里的 html 容器元素是 id 为 approvalId 的 div。

import React, { useEffect, useState } from 'react';
import Script from 'next/script';

const Approval = ({ mode = process.env.NODE_ENV }) => {
  const handleScriptLoad = () => {
    window.ReactApproval.mount(document.querySelector('#approvalId'));
    setTimeout(() => {
      window.ReactApproval.proxy.setMaskCloseable(false);
    }, 1200);
  };
  let sdkSrc = 'https://react.module.ijklh.com/exports/react-approval.production.umd.min.js';
  if (mode === 'development') {
    sdkSrc = '/exports/react-approval.development.umd.min.js';
  }

  return (
    <React.Fragment>
      <Script
	src={sdkSrc}
	onLoad={handleScriptLoad}
      />
      <div className="u-col is-center">
	<div id="approvalId"></div>
	{/* <div className='u-mt16 u-t14'><i>我们不接受多于 10 元的赞赏,请不要过度赞赏,谢谢~</i></div> */}
      </div>
    </React.Fragment>
  );
};

export default Approval;

在任意 html 网页中使用组件 react-approval

在 head 中引入 link 样式

<link rel="stylesheet" href="https://www.uqugu.com/static/vendor/uqugu-modules/styles/index.css">

在 body 中安装赞赏组件

<div id="approvalId" class="u-mb48"></div>
<script src="https://react.module.ijklh.com/exports/react-approval.production.umd.min.js"></script>
<script>
var approval = document.querySelector('#approvalId');
window.ReactApproval.mount(document.querySelector('#approvalId'));
// window.ReactApproval.proxy.setOpen(true);
</script>

试试看,好不好用,你说了算。

关于本文如您有任何想法和意见,欢迎与我们联系,邮箱地址zhi@uqugu.com
您对本文有什么看法,喜欢或者不喜欢都可以发表意见。