Merge remote-tracking branch 'origin/main' into pr/1208nn/1700

This commit is contained in:
tangly1024.com
2023-12-27 18:54:17 +08:00
15 changed files with 116 additions and 17 deletions

View File

@@ -101,7 +101,7 @@ const ExternalPlugin = (props) => {
{ANALYTICS_51LA_ID && ANALYTICS_51LA_CK && <LA51/>} {ANALYTICS_51LA_ID && ANALYTICS_51LA_CK && <LA51/>}
{ANALYTICS_51LA_ID && ANALYTICS_51LA_CK && (<> {ANALYTICS_51LA_ID && ANALYTICS_51LA_CK && (<>
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js" defer/> <script id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js" defer/>
{/* <script async dangerouslySetInnerHTML={{ {/* <script async dangerouslySetInnerHTML={{
__html: ` __html: `
LA.init({id:"${ANALYTICS_51LA_ID}",ck:"${ANALYTICS_51LA_CK}",hashMode:true,autoTrack:true}) LA.init({id:"${ANALYTICS_51LA_ID}",ck:"${ANALYTICS_51LA_CK}",hashMode:true,autoTrack:true})
@@ -139,7 +139,7 @@ const ExternalPlugin = (props) => {
/> />
</>)} </>)}
{AD_WWADS_ID && <script type="text/javascript" charSet="UTF-8" src="https://cdn.wwads.cn/js/makemoney.js" async></script>} {AD_WWADS_ID && <script type="text/javascript" src="https://cdn.wwads.cn/js/makemoney.js" async></script>}
{COMMENT_TWIKOO_ENV_ID && <script defer src={COMMENT_TWIKOO_CDN_URL} />} {COMMENT_TWIKOO_ENV_ID && <script defer src={COMMENT_TWIKOO_CDN_URL} />}

View File

@@ -41,6 +41,7 @@ export default {
ARTICLE_DETAIL: 'Article Details', ARTICLE_DETAIL: 'Article Details',
PASSWORD_ERROR: 'Password Error!', PASSWORD_ERROR: 'Password Error!',
ARTICLE_LOCK_TIPS: 'Please Enter the password:', ARTICLE_LOCK_TIPS: 'Please Enter the password:',
NO_RESULTS_FOUND: 'No results found.',
SUBMIT: 'Submit', SUBMIT: 'Submit',
POST_TIME: 'Post on', POST_TIME: 'Post on',
LAST_EDITED_TIME: 'Last edited', LAST_EDITED_TIME: 'Last edited',
@@ -52,8 +53,8 @@ export default {
ANNOUNCEMENT: 'Announcement', ANNOUNCEMENT: 'Announcement',
START_READING: 'Start Reading', START_READING: 'Start Reading',
MINUTE: 'min', MINUTE: 'min',
WORD_COUNT: 'W.C.' WORD_COUNT: 'Words',
READ_TIME: 'Read Time'
}, },
PAGINATION: { PAGINATION: {
PREV: 'Prev', PREV: 'Prev',
@@ -66,5 +67,10 @@ export default {
POST: { POST: {
BACK: 'Back', BACK: 'Back',
TOP: 'Top' TOP: 'Top'
},
MAILCHIMP: {
SUBSCRIBE: 'Subscribe',
MSG: 'Get the latest news and articles to your inbox every month.',
EMAIL: 'Email'
} }
} }

View File

@@ -40,6 +40,7 @@ export default {
VIEWS: '次查看', VIEWS: '次查看',
COPYRIGHT_NOTICE: '本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。', COPYRIGHT_NOTICE: '本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。',
RESULT_OF_SEARCH: '篇搜索到的结果', RESULT_OF_SEARCH: '篇搜索到的结果',
NO_RESULTS_FOUND: '没有找到文章',
ARTICLE_DETAIL: '文章详情', ARTICLE_DETAIL: '文章详情',
PASSWORD_ERROR: '密码错误!', PASSWORD_ERROR: '密码错误!',
ARTICLE_LOCK_TIPS: '文章已上锁,请输入访问密码', ARTICLE_LOCK_TIPS: '文章已上锁,请输入访问密码',
@@ -54,7 +55,8 @@ export default {
ANNOUNCEMENT: '公告', ANNOUNCEMENT: '公告',
START_READING: '开始阅读', START_READING: '开始阅读',
MINUTE: '分钟', MINUTE: '分钟',
WORD_COUNT: '字数' WORD_COUNT: '字数',
READ_TIME: '阅读时长'
}, },
PAGINATION: { PAGINATION: {
PREV: '上页', PREV: '上页',
@@ -67,5 +69,10 @@ export default {
POST: { POST: {
BACK: '返回上页', BACK: '返回上页',
TOP: '回到顶部' TOP: '回到顶部'
},
MAILCHIMP: {
SUBSCRIBE: '邮件订阅',
MSG: '订阅以获取每月更新的新闻和文章,直接发送至您的邮箱。',
EMAIL: '邮箱'
} }
} }

View File

@@ -113,7 +113,7 @@ const isIterable = obj =>
async function filterByMemCache(allPosts, keyword) { async function filterByMemCache(allPosts, keyword) {
const filterPosts = [] const filterPosts = []
if (keyword) { if (keyword) {
keyword = keyword.trim() keyword = keyword.trim().toLowerCase()
} }
for (const post of allPosts) { for (const post of allPosts) {
const cacheKey = 'page_block_' + post.id const cacheKey = 'page_block_' + post.id
@@ -131,7 +131,7 @@ async function filterByMemCache(allPosts, keyword) {
if (!c) { if (!c) {
continue continue
} }
const index = c.toLowerCase().indexOf(keyword.toLowerCase()) const index = c.toLowerCase().indexOf(keyword)
if (index > -1) { if (index > -1) {
hit = true hit = true
hitCount += 1 hitCount += 1

View File

@@ -13,6 +13,7 @@ import { useFukasawaGlobal } from '..'
import CONFIG from '@/themes/fukasawa/config' import CONFIG from '@/themes/fukasawa/config'
import { AdSlot } from '@/components/GoogleAdsense' import { AdSlot } from '@/components/GoogleAdsense'
import { siteConfig } from '@/lib/config' import { siteConfig } from '@/lib/config'
import MailChimpForm from './MailChimpForm'
/** /**
* 侧边栏 * 侧边栏
@@ -82,7 +83,11 @@ function AsideLeft(props) {
</section> </section>
<section> <section>
<AdSlot type='in-article'/> <MailChimpForm />
</section>
<section>
<AdSlot type='in-article' />
</section> </section>
{router.asPath !== '/tag' && <section className='flex flex-col'> {router.asPath !== '/tag' && <section className='flex flex-col'>

View File

@@ -11,6 +11,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
post.pageCoverThumbnail = siteInfo?.pageCover post.pageCoverThumbnail = siteInfo?.pageCover
} }
const showPageCover = siteConfig('FUKASAWA_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail const showPageCover = siteConfig('FUKASAWA_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
const SUB_PATH = siteConfig('SUB_PATH', '')
return ( return (
<div <div
@@ -25,7 +26,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
{/* 封面图 */} {/* 封面图 */}
{showPageCover && ( {showPageCover && (
<div className="flex-grow mb-3 w-full duration-200 cursor-pointer transform overflow-hidden"> <div className="flex-grow mb-3 w-full duration-200 cursor-pointer transform overflow-hidden">
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior> <Link href={`${SUB_PATH}/${post.slug}`} passHref legacyBehavior>
<LazyImage <LazyImage
src={post?.pageCoverThumbnail} src={post?.pageCoverThumbnail}
alt={post?.title || siteConfig('TITLE')} alt={post?.title || siteConfig('TITLE')}
@@ -37,7 +38,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
{/* 文字部分 */} {/* 文字部分 */}
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} <Link passHref href={`${SUB_PATH}/${post.slug}`}
className={`break-words cursor-pointer font-bold hover:underline text-xl ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`} className={`break-words cursor-pointer font-bold hover:underline text-xl ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
> >
{post.title} {post.title}

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
/** /**
* 空白博客 列表 * 空白博客 列表
@@ -5,8 +6,9 @@
* @constructor * @constructor
*/ */
const BlogListEmpty = ({ currentSearch }) => { const BlogListEmpty = ({ currentSearch }) => {
const { locale } = useGlobal()
return <div className='flex items-center justify-center min-h-screen mx-auto md:-mt-20'> return <div className='flex items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>没有找到文章 {(currentSearch && <div>{currentSearch}</div>)}</p> <p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
</div> </div>
} }
export default BlogListEmpty export default BlogListEmpty

View File

@@ -0,0 +1,62 @@
import { useEffect, useRef, useState } from 'react'
import { subscribeToNewsletter } from '@/lib/mailchimp'
import { siteConfig } from '@/lib/config'
import CONFIG from '../config'
import { useGlobal } from '@/lib/global'
/**
* 邮件订阅表单
* @returns
*/
export default function MailChimpForm() {
const formRef = useRef()
const [success, setSuccess] = useState(false)
const { locale } = useGlobal()
useEffect(() => {
const form = formRef.current
const handleSubmit = (e) => {
e.preventDefault()
const email = document.querySelector('#newsletter').value
subscribeToNewsletter(email).then(response => {
console.log('Subscription succeeded:', response)
// 在此处添加成功订阅后的操作
setSuccess(true)
})
.catch(error => {
console.error('Subscription failed:', error)
// 在此处添加订阅失败后的操作
})
}
form?.addEventListener('submit', handleSubmit)
return () => {
form?.removeEventListener('submit', handleSubmit)
}
}, [subscribeToNewsletter])
return <>
{siteConfig('FUKASAWA_MAILCHIMP_FORM', null, CONFIG) && <div className="sm:col-span-6 md:col-span-3 lg:col-span-3">
<h6 className="text-gray-800 font-medium mb-2">{locale.MAILCHIMP.SUBSCRIBE}</h6>
<p className="text-sm text-gray-600 mb-4">{locale.MAILCHIMP.MSG}</p>
<form ref={formRef}>
<div className="flex flex-wrap mb-4">
<div className="w-full">
<label className="block text-sm sr-only" htmlFor="newsletter">{locale.MAILCHIMP.EMAIL}</label>
<div className="relative flex items-center max-w-xs">
<input disabled={success} id="newsletter" type="email" className="form-input w-full text-gray-800 px-3 py-2 pr-12 text-sm" placeholder={locale.MAILCHIMP.EMAIL} required />
<button disabled={success} type="submit" className="absolute inset-0 left-auto" aria-label="Subscribe">
<span className="absolute inset-0 right-auto w-px -ml-px my-2 bg-gray-300" aria-hidden="true"></span>
<svg className="w-3 h-3 fill-current text-blue-600 mx-3 shrink-0" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
<path d="M11.707 5.293L7 .586 5.586 2l3 3H0v2h8.586l-3 3L7 11.414l4.707-4.707a1 1 0 000-1.414z" fillRule="nonzero" />
</svg>
</button>
</div>
{/* Success message */}
{success && <p className="mt-2 text-green-600 text-sm">Thanks for subscribing!</p>}
</div>
</div>
</form>
</div>
}
</>
}

View File

@@ -1,4 +1,5 @@
const CONFIG = { const CONFIG = {
FUKASAWA_MAILCHIMP_FORM: false, // 邮件订阅表单
FUKASAWA_POST_LIST_COVER: true, // 文章列表显示图片封面 FUKASAWA_POST_LIST_COVER: true, // 文章列表显示图片封面
FUKASAWA_POST_LIST_COVER_FORCE: false, // 即使没有封面也将站点背景图设置为封面 FUKASAWA_POST_LIST_COVER_FORCE: false, // 即使没有封面也将站点背景图设置为封面

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
/** /**
* 空白博客 列表 * 空白博客 列表
@@ -5,8 +6,9 @@
* @constructor * @constructor
*/ */
const NavPostListEmpty = ({ currentSearch }) => { const NavPostListEmpty = ({ currentSearch }) => {
const { locale } = useGlobal()
return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'> return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>没有找到文章 {(currentSearch && <div>{currentSearch}</div>)}</p> <p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
</div> </div>
} }
export default NavPostListEmpty export default NavPostListEmpty

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
/** /**
* 空白博客 列表 * 空白博客 列表
@@ -5,8 +6,9 @@
* @constructor * @constructor
*/ */
const BlogPostListEmpty = ({ currentSearch }) => { const BlogPostListEmpty = ({ currentSearch }) => {
const { locale } = useGlobal()
return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'> return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>没有找到文章 {(currentSearch && <div>{currentSearch}</div>)}</p> <p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
</div> </div>
} }
export default BlogPostListEmpty export default BlogPostListEmpty

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
/** /**
* 空白博客 列表 * 空白博客 列表
@@ -5,8 +6,9 @@
* @constructor * @constructor
*/ */
const BlogPostListEmpty = ({ currentSearch }) => { const BlogPostListEmpty = ({ currentSearch }) => {
const { locale } = useGlobal()
return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'> return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>没有找到文章 {(currentSearch && <div>{currentSearch}</div>)}</p> <p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
</div> </div>
} }
export default BlogPostListEmpty export default BlogPostListEmpty

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
/** /**
* 空白博客 列表 * 空白博客 列表
@@ -5,8 +6,9 @@
* @constructor * @constructor
*/ */
const NavPostListEmpty = ({ currentSearch }) => { const NavPostListEmpty = ({ currentSearch }) => {
const { locale } = useGlobal()
return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'> return <div className='flex w-full items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>没有找到文章 {(currentSearch && <div>{currentSearch}</div>)}</p> <p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
</div> </div>
} }
export default NavPostListEmpty export default NavPostListEmpty

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
/** /**
* 空白博客 列表 * 空白博客 列表
@@ -5,8 +6,9 @@
* @constructor * @constructor
*/ */
const BlogPostListEmpty = ({ currentSearch }) => { const BlogPostListEmpty = ({ currentSearch }) => {
const { locale } = useGlobal()
return <div className='flex items-center justify-center min-h-screen mx-auto md:-mt-20'> return <div className='flex items-center justify-center min-h-screen mx-auto md:-mt-20'>
<p className='text-gray-500 dark:text-gray-300'>没有找到文章 {(currentSearch && <div>{currentSearch}</div>)}</p> <p className='text-gray-500 dark:text-gray-300'>{locale.COMMON.NO_RESULTS_FOUND} {(currentSearch && <div>{currentSearch}</div>)}</p>
</div> </div>
} }
export default BlogPostListEmpty export default BlogPostListEmpty

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
import { useEffect } from 'react' import { useEffect } from 'react'
/** /**
@@ -9,8 +10,12 @@ export default function WordCount() {
countWords() countWords()
}) })
const { locale } = useGlobal()
return <div id='wordCountWrapper' className='flex justify-center my-auto font-light'> return <div id='wordCountWrapper' className='flex justify-center my-auto font-light'>
<i className='mr-1 fas fa-file-word my-auto' /> <span className='hidden md:block'>本文字数</span> <strong id='wordCount'>0</strong> &nbsp;|&nbsp; <i className='mr-1 fas fa-clock my-auto' /> <span className='hidden md:block'> </span> <strong id='readTime'>0</strong> <i className='mr-1 fas fa-file-word my-auto' />
<span className='hidden md:block'>{locale.COMMON.WORD_COUNT}</span>
<strong id='wordCount'>0</strong> &nbsp;|&nbsp; <i className='mr-1 fas fa-clock my-auto' />{locale.COMMON.READ_TIME} <span className='hidden md:block'></span> <strong id='readTime'>0</strong> {locale.COMMON.MINUTE}
</div> </div>
} }