mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 15:09:22 +00:00
feat - 分享功能
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
370
components/ShareButtons.js
Normal 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
|
||||
@@ -17,7 +17,7 @@ export default {
|
||||
NO_TAG: 'NoTag',
|
||||
CATEGORY: '分类',
|
||||
SHARE: '分享',
|
||||
SCAN_QR_CODE: '扫一扫二维码',
|
||||
SCAN_QR_CODE: '微信扫码分享',
|
||||
URL_COPIED: '链接已复制!',
|
||||
TABLE_OF_CONTENTS: '目录',
|
||||
RELATE_POSTS: '相关文章',
|
||||
|
||||
Reference in New Issue
Block a user