feat - 分享功能

This commit is contained in:
tangly1024.com
2023-04-26 16:11:01 +08:00
parent c71d51c800
commit 4ca8f39a6b
5 changed files with 385 additions and 107 deletions

View File

@@ -96,7 +96,9 @@ const BLOG = {
BACKGROUND_DARK: '#000000', // use hex value, don't forget '#'
SUB_PATH: '', // leave this empty unless you want to deploy in a folder
POST_SHARE_BAR_ENABLE: process.env.NEXT_PUBLIC_POST_SHARE_BAR || 'false', // 文章分享功能 ,将在底部显示一个分享条
POST_SHARE_BAR_ENABLE: process.env.NEXT_PUBLIC_POST_SHARE_BAR || 'true', // 文章分享功能 ,将在底部显示一个分享条
POSTS_SHARE_SERVICES: process.env.NEXT_PUBLIC_POST_SHARE_SERVICES || 'link,wechat,qq,weibo,email,facebook,twitter,telegram,messenger,line,reddit,whatsapp,linkedin', // 分享的服務,选填逗号隔开
// 所有支持的分享服务link(复制链接),wechat(微信),qq,weibo(微博),email(邮件),facebook,twitter,telegram,messenger,line,reddit,whatsapp,linkedin,vkshare,okshare,tumblr,livejournal,mailru,viber,workplace,pocket,instapaper,hatena
POST_URL_PREFIX: process.env.NEXT_PUBLIC_POST_URL_PREFIX || 'article',
// POST类型文章的默认路径前缀例如默认POST类型的路径是 /article/[slug]

View File

@@ -1,15 +1,10 @@
import BLOG from '@/blog.config'
import { useRouter } from 'next/router'
import React from 'react'
import { createPopper } from '@popperjs/core'
import copy from 'copy-to-clipboard'
import QRCode from 'qrcode.react'
import { useGlobal } from '@/lib/global'
import ShareButtons from './ShareButtons'
const ShareBar = ({ post }) => {
const router = useRouter()
const [qrCodeShow, setQrCodeShow] = React.useState(false)
const { locale } = useGlobal()
if (!JSON.parse(BLOG.POST_SHARE_BAR_ENABLE) || !post || post?.type !== 'Post') {
return <></>
@@ -17,71 +12,16 @@ const ShareBar = ({ post }) => {
const shareUrl = BLOG.LINK + router.asPath
// 二维码悬浮
const btnRef = React.createRef()
const popoverRef = React.createRef()
const openPopover = () => {
createPopper(btnRef.current, popoverRef.current, {
placement: 'top'
})
setQrCodeShow(true)
}
const closePopover = () => {
setQrCodeShow(false)
}
const copyUrl = () => {
copy(shareUrl)
alert(locale.COMMON.URL_COPIED)
}
return <div id='share-bar'
className='py-2 text-gray-500 text-center space-x-2 flex my-1 dark:text-gray-200 overflow-visible'>
<div className='hidden md:block text-gray-800 dark:text-gray-300 mr-2 my-2 whitespace-nowrap'>{locale.COMMON.SHARE}:</div>
<div className='text-3xl cursor-pointer w-6'>
<a className='text-blue-700' href={`https://www.facebook.com/sharer.php?u=${shareUrl}`} >
<i className='fab fa-facebook-square'/>
</a>
</div>
<div className='text-3xl cursor-pointer w-6'>
<a className='text-blue-400' target='_blank' rel='noreferrer' href={`https://twitter.com/intent/tweet?title=${post.title}&url${shareUrl}`} >
<i className='fab fa-twitter-square'/>
</a>
</div>
<div className='text-3xl cursor-pointer w-6'>
<a className='text-blue-500' href={`https://telegram.me/share/url?url=${shareUrl}&text=${post.title}`} >
<i className='fab fa-telegram'/>
</a>
</div>
<div className='cursor-pointer text-2xl w-6'>
<a className='text-green-600' ref={btnRef} onMouseEnter={openPopover} onMouseLeave={closePopover}>
<i className='fab fa-weixin'/>
<div ref={popoverRef} className={(qrCodeShow ? 'opacity-100 ' : 'invisible opacity-0') + ' transition-all duration-200 text-center py-2'}>
<div className='p-2 bg-white border-0 duration-200 transform block z-40 font-normal shadow-xl mr-10'>
<QRCode value={shareUrl} fgColor='#000000' />
</div>
<span className='bg-white text-black font-semibold p-1 mb-0 rounded-t-lg text-sm mx-auto mr-10'>
{locale.COMMON.SCAN_QR_CODE}
</span>
</div>
</a>
</div>
<div className='cursor-pointer text-2xl w-6'>
<a className='text-red-600' target='_blank' rel='noreferrer' href={`https://service.weibo.com/share/share.php?url=${shareUrl}&title=${post.title}`} >
<i className='fab fa-weibo'/>
</a>
</div>
<div className='cursor-pointer text-2xl w-6'>
<a className='text-blue-400' target='_blank' rel='noreferrer' href={`http://connect.qq.com/widget/shareqq/index.html?url=${shareUrl}&sharesource=qzone&title=${post.title}&desc=${post.summary}`} >
<i className='fab fa-qq'/>
</a>
</div>
<div className='cursor-pointer text-2xl w-6'>
<a className='text-yellow-600' onClick={copyUrl} >
<i className='fas fa-link'/>
</a>
</div>
return <div className='py-1 flex'>
<ShareButtons shareUrl={shareUrl} title={post.title} image={post.pageCover} body={
post.title +
' | ' +
BLOG.TITLE +
' ' +
shareUrl +
' ' +
post.summary
} />
</div>
}
export default ShareBar

View File

@@ -1,34 +0,0 @@
import React from 'react'
import ShareBar from './ShareBar'
/**
* 悬浮在屏幕右下角,分享按钮
* @returns {JSX.Element}
* @constructor
*/
const ShareButton = ({ post }) => {
const [popoverShow, setPopoverShow] = React.useState(false)
const btnRef = React.createRef()
const openPopover = () => {
setPopoverShow(true)
}
const closePopover = () => {
setPopoverShow(false)
}
return (
<div className='my-2'
onMouseEnter={() => { openPopover() }}
onMouseLeave={() => { closePopover() }}>
<div className={(popoverShow ? 'opacity-100' : 'opacity-0') + ' duration-200 ease-in-out font-normal'}>
<ShareBar post={post}/>
</div>
<div ref={btnRef}
className='z-20 border dark:border-gray-500 dark:bg-gray-600 bg-white cursor-pointer text-md hover:shadow-2xl shadow-lg'>
<i className='fas fa-share-alt-square transform duration-200 hover:scale-150 dark:text-gray-200 p-4' title='share' />
</div>
</div>
)
}
export default ShareButton

370
components/ShareButtons.js Normal file
View File

@@ -0,0 +1,370 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import copy from 'copy-to-clipboard'
import QRCode from 'qrcode.react'
import { useState } from 'react'
import {
FacebookShareButton,
FacebookIcon,
FacebookMessengerShareButton,
FacebookMessengerIcon,
RedditShareButton,
RedditIcon,
LineShareButton,
LineIcon,
EmailShareButton,
EmailIcon,
TwitterShareButton,
TwitterIcon,
TelegramShareButton,
TelegramIcon,
WhatsappShareButton,
WhatsappIcon,
LinkedinShareButton,
LinkedinIcon,
PinterestShareButton,
PinterestIcon,
VKIcon,
VKShareButton,
OKShareButton,
OKIcon,
TumblrShareButton,
TumblrIcon,
LivejournalIcon,
LivejournalShareButton,
MailruShareButton,
MailruIcon,
ViberIcon,
ViberShareButton,
WorkplaceShareButton,
WorkplaceIcon,
WeiboShareButton,
WeiboIcon,
PocketShareButton,
PocketIcon,
InstapaperShareButton,
InstapaperIcon,
HatenaShareButton,
HatenaIcon
} from 'react-share'
/**
* @author https://github.com/txs
* @param {*} param0
* @returns
*/
const ShareButtons = ({ shareUrl, title, body, image }) => {
const services = BLOG.POSTS_SHARE_SERVICES.split(',')
const titleWithSiteInfo = title + ' | ' + BLOG.TITLE
const { locale } = useGlobal()
const [qrCodeShow, setQrCodeShow] = useState(false)
const copyUrl = () => {
copy(shareUrl)
alert(locale.COMMON.URL_COPIED)
}
const openPopover = () => {
setQrCodeShow(true)
}
const closePopover = () => {
setQrCodeShow(false)
}
return (
<>
{services.map(singleService => {
if (singleService === 'facebook') {
return (
<FacebookShareButton
key={singleService}
url={shareUrl}
className="mx-1"
>
<FacebookIcon size={32} round />
</FacebookShareButton>
)
}
if (singleService === 'messenger') {
return (
<FacebookMessengerShareButton
key={singleService}
url={shareUrl}
appId={BLOG.FACEBOOK_APP_ID}
className="mx-1"
>
<FacebookMessengerIcon size={32} round />
</FacebookMessengerShareButton>
)
}
if (singleService === 'line') {
return (
<LineShareButton
key={singleService}
url={shareUrl}
className="mx-1"
>
<LineIcon size={32} round />
</LineShareButton>
)
}
if (singleService === 'reddit') {
return (
<RedditShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
windowWidth={660}
windowHeight={460}
className="mx-1"
>
<RedditIcon size={32} round />
</RedditShareButton>
)
}
if (singleService === 'email') {
return (
<EmailShareButton
key={singleService}
url={shareUrl}
subject={titleWithSiteInfo}
body={body}
className="mx-1"
>
<EmailIcon size={32} round />
</EmailShareButton>
)
}
if (singleService === 'twitter') {
return (
<TwitterShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<TwitterIcon size={32} round />
</TwitterShareButton>
)
}
if (singleService === 'telegram') {
return (
<TelegramShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<TelegramIcon size={32} round />
</TelegramShareButton>
)
}
if (singleService === 'whatsapp') {
return (
<WhatsappShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
separator=":: "
className="mx-1"
>
<WhatsappIcon size={32} round />
</WhatsappShareButton>
)
}
if (singleService === 'linkedin') {
return (
<LinkedinShareButton
key={singleService}
url={shareUrl}
className="mx-1"
>
<LinkedinIcon size={32} round />
</LinkedinShareButton>
)
}
if (singleService === 'pinterest') {
return (
<PinterestShareButton
key={singleService}
url={shareUrl}
media={image}
className="mx-1"
>
<PinterestIcon size={32} round />
</PinterestShareButton>
)
}
if (singleService === 'vkshare') {
return (
<VKShareButton
key={singleService}
url={shareUrl}
image={image}
className="mx-1"
>
<VKIcon size={32} round />
</VKShareButton>
)
}
if (singleService === 'okshare') {
return (
<OKShareButton
key={singleService}
url={shareUrl}
image={image}
className="mx-1"
>
<OKIcon size={32} round />
</OKShareButton>
)
}
if (singleService === 'tumblr') {
return (
<TumblrShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<TumblrIcon size={32} round />
</TumblrShareButton>
)
}
if (singleService === 'livejournal') {
return (
<LivejournalShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
description={shareUrl}
className="mx-1"
>
<LivejournalIcon size={32} round />
</LivejournalShareButton>
)
}
if (singleService === 'mailru') {
return (
<MailruShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<MailruIcon size={32} round />
</MailruShareButton>
)
}
if (singleService === 'viber') {
return (
<ViberShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<ViberIcon size={32} round />
</ViberShareButton>
)
}
if (singleService === 'workplace') {
return (
<WorkplaceShareButton
key={singleService}
url={shareUrl}
quote={titleWithSiteInfo}
className="mx-1"
>
<WorkplaceIcon size={32} round />
</WorkplaceShareButton>
)
}
if (singleService === 'weibo') {
return (
<WeiboShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
image={image}
className="mx-1"
>
<WeiboIcon size={32} round />
</WeiboShareButton>
)
}
if (singleService === 'pocket') {
return (
<PocketShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<PocketIcon size={32} round />
</PocketShareButton>
)
}
if (singleService === 'instapaper') {
return (
<InstapaperShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
className="mx-1"
>
<InstapaperIcon size={32} round />
</InstapaperShareButton>
)
}
if (singleService === 'hatena') {
return (
<HatenaShareButton
key={singleService}
url={shareUrl}
title={titleWithSiteInfo}
windowWidth={660}
windowHeight={460}
className="mx-1"
>
<HatenaIcon size={32} round />
</HatenaShareButton>
)
}
if (singleService === 'qq') {
return <button key={singleService} className='cursor-pointer w-8 h-8 bg-blue-600 text-white rounded-full mx-1'>
<div target='_blank' rel='noreferrer' href={`http://connect.qq.com/widget/shareqq/index.html?url=${shareUrl}&sharesource=qzone&title=${title}&desc=${body}`} >
<i className='fab fa-qq' />
</div>
</button>
}
if (singleService === 'wechat') {
return <button onMouseEnter={openPopover} onMouseLeave={closePopover} aria-label={singleService} key={singleService} className='relative cursor-pointer w-8 h-8 bg-green-600 text-white rounded-full mx-1'>
<div id='wechat-button'>
<i className='fab fa-weixin' />
</div>
<div id='pop' className={(qrCodeShow ? 'opacity-100 ' : ' invisible opacity-0') + ' z-40 absolute bottom-10 -left-10 bg-white shadow-xl transition-all duration-200 text-center'}>
<div className='p-2 mt-1'>
<QRCode value={shareUrl} fgColor='#000000' />
</div>
<span className='text-black font-semibold p-1 rounded-t-lg text-sm mx-auto mb-1'>
{locale.COMMON.SCAN_QR_CODE}
</span>
</div>
</button>
}
if (singleService === 'link') {
return <button aria-label={singleService} key={singleService} className='cursor-pointer w-8 h-8 bg-yellow-500 text-white rounded-full mx-1'>
<div alt={locale.COMMON.URL_COPIED} onClick={copyUrl} >
<i className='fas fa-link' />
</div>
</button>
}
return <></>
})}
</>
)
}
export default ShareButtons

View File

@@ -17,7 +17,7 @@ export default {
NO_TAG: 'NoTag',
CATEGORY: '分类',
SHARE: '分享',
SCAN_QR_CODE: '扫一扫二维码',
SCAN_QR_CODE: '微信扫码分享',
URL_COPIED: '链接已复制!',
TABLE_OF_CONTENTS: '目录',
RELATE_POSTS: '相关文章',