From 18916e448f1b6f0f6ff6e5c85094ecc6d11907ff Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Sun, 29 Oct 2023 22:45:37 +0800 Subject: [PATCH 01/48] =?UTF-8?q?CONFIG-TABLE=20=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E9=A6=96=E8=A1=8C=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/notion/getNotionData.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index f885f22b..6c01c294 100755 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -272,6 +272,7 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { // 文章计数 let postCount = 0 + // 查找所有的Post和Page const allPages = collectionData.filter(post => { if (post?.type === 'Post' && post.status === 'Published') { @@ -282,6 +283,16 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { (post?.status === 'Invisible' || post?.status === 'Published') }) + // 从notion中读取配置 + const configPage = collectionData.find(post => { + return post && post?.type && post?.type === 'CONFIG' + }) + + if (configPage) { + const config = await getPostBlocks(configPage.id, 'config-table') + console.log('配置中心', configPage, config) + } + // Sort by date if (BLOG.POSTS_SORT_BY === 'date') { allPages.sort((a, b) => { From ff552b7de4a64aee829346e1ec22e7bb24ccb58e Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Mon, 30 Oct 2023 22:39:06 +0800 Subject: [PATCH 02/48] =?UTF-8?q?=E4=BB=8ENotion=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/notion/getNotionConfig.js | 137 ++++++++++++++++++++++++++++++++ lib/notion/getNotionData.js | 13 +-- lib/notion/getPageProperties.js | 10 +++ next-sitemap.config.js | 3 + 4 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 lib/notion/getNotionConfig.js diff --git a/lib/notion/getNotionConfig.js b/lib/notion/getNotionConfig.js new file mode 100644 index 00000000..7a475ed3 --- /dev/null +++ b/lib/notion/getNotionConfig.js @@ -0,0 +1,137 @@ +/** + * 从Notion中读取站点配置; + * 在Notion模板中创建一个类型为CONFIG的页面,再添加一个数据库表格,即可用于填写配置 + * Notion数据库配置优先级最高,将覆盖vercel环境变量以及blog.config.js中的配置 + * --注意-- + * 数据库请从模板复制 https://www.notion.so/tanghh/287869a92e3d4d598cf366bd6994755e + * + */ +import { getDateValue, getTextContent } from 'notion-utils' +import { getPostBlocks } from './getPostBlocks' +import getAllPageIds from './getAllPageIds' +import BLOG from '@/blog.config' + +/** + * 从Notion中读取Config配置表 + * @param {*} allPages + * @returns + */ +export async function getConfigMapFromConfigPage(allPages) { + // 默认返回配置文件 + const notionConfig = BLOG + + if (!allPages || !Array.isArray(allPages) || allPages.length === 0) { + console.warn('[Notion配置] 忽略的配置', allPages, typeof allPages) + return null + } + const configPage = allPages?.find(post => { + return post && post?.type && post?.type === 'CONFIG' + }) + + if (!configPage) { + console.warn('[Notion配置]未找到配置页面', allPages, typeof allPages) + return null + } + const configPageId = configPage.id + + console.log('[Notion配置]请求配置数据 ', configPage.id) + const pageRecordMap = await getPostBlocks(configPageId, 'config-table') + // console.log('配置中心Page', configPageId, pageRecordMap) + const content = pageRecordMap.block[configPageId].value.content + + if (!content) { + console.warn('[Notion配置]未找到配置表格', pageRecordMap.block[configPageId], pageRecordMap.block[configPageId].value) + return null + } + + // 找到配置文件中的database + // for (const contentId of content) { + // console.log('内容', contentId, configPageRecordMap.block[contentId].value.type === 'collection_view') + // } + const configTableId = content?.find(contentId => { + return pageRecordMap.block[contentId].value.type === 'collection_view' + }) + + // eslint-disable-next-line no-constant-condition, no-self-compare + if (!configTableId) { + console.warn('[Notion配置]未找到配置表格数据', pageRecordMap.block[configPageId], pageRecordMap.block[configPageId].value) + return null + } + + // 页面查找 + const databaseRecordMap = pageRecordMap.block[configTableId] + const block = pageRecordMap.block || {} + const rawMetadata = databaseRecordMap.value + // Check Type Page-Database和Inline-Database + if ( + rawMetadata?.type !== 'collection_view_page' && rawMetadata?.type !== 'collection_view' + ) { + console.error(`pageId "${configTableId}" is not a database`) + return null + } + console.log('表格', databaseRecordMap, block, rawMetadata) + const collectionId = rawMetadata?.collection_id + const collection = pageRecordMap.collection[collectionId].value + const collectionQuery = pageRecordMap.collection_query + const collectionView = pageRecordMap.collection_view + const schema = collection?.schema + const viewIds = rawMetadata?.view_ids + const pageIds = getAllPageIds(collectionQuery, collectionId, collectionView, viewIds) + if (pageIds?.length === 0) { + console.error('[Notion配置]获取到的文章列表为空,请检查notion模板', collectionQuery, collection, collectionView, viewIds, databaseRecordMap) + } + // 遍历用户的表格 + for (let i = 0; i < pageIds.length; i++) { + const id = pageIds[i] + const value = block[id]?.value + if (!value) { + continue + } + const rawProperties = Object.entries(block?.[id]?.value?.properties || []) + const excludeProperties = ['date', 'select', 'multi_select', 'person'] + const properties = {} + for (let i = 0; i < rawProperties.length; i++) { + const [key, val] = rawProperties[i] + properties.id = id + if (schema[key]?.type && !excludeProperties.includes(schema[key].type)) { + properties[schema[key].name] = getTextContent(val) + } else { + switch (schema[key]?.type) { + case 'date': { + const dateProperty = getDateValue(val) + delete dateProperty.type + properties[schema[key].name] = dateProperty + break + } + case 'select': + case 'multi_select': { + const selects = getTextContent(val) + if (selects[0]?.length) { + properties[schema[key].name] = selects.split(',') + } + break + } + default: + break + } + } + } + + if (properties) { + // 将表格中的字段映射成 英文 + const config = { + enable: properties['启用'] === 'Yes', + key: properties['配置名'], + value: properties['配置值'] + } + + // 只导入生效的配置 + if (config.enable) { + console.log('[覆盖代码配置]', config.key) + notionConfig[config.key] = config.value + } + } + } + + return notionConfig +} diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index 6c01c294..3d063bcf 100755 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -8,6 +8,7 @@ import getAllPageIds from './getAllPageIds' import { getAllTags } from './getAllTags' import getPageProperties from './getPageProperties' import { mapImgUrl, compressImage } from './mapImage' +import { getConfigMapFromConfigPage } from './getNotionConfig' /** * 获取博客数据 @@ -283,15 +284,8 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { (post?.status === 'Invisible' || post?.status === 'Published') }) - // 从notion中读取配置 - const configPage = collectionData.find(post => { - return post && post?.type && post?.type === 'CONFIG' - }) - - if (configPage) { - const config = await getPostBlocks(configPage.id, 'config-table') - console.log('配置中心', configPage, config) - } + // 站点配置优先读取配置表格,否则读取blog.config.js 文件 + const CONFIG = await getConfigMapFromConfigPage(collectionData) || BLOG // Sort by date if (BLOG.POSTS_SORT_BY === 'date') { @@ -311,6 +305,7 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { const allNavPages = getNavPages({ allPages }) return { + CONFIG, notice, siteInfo, allPages, diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index ddf47f3e..3ea1ce28 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -6,6 +6,15 @@ import formatDate from '../formatDate' import md5 from 'js-md5' import { mapImgUrl } from './mapImage' +/** + * 获取页面元素成员属性 + * @param {*} id + * @param {*} block + * @param {*} schema + * @param {*} authToken + * @param {*} tagOptions + * @returns + */ export default async function getPageProperties(id, block, schema, authToken, tagOptions) { const rawProperties = Object.entries(block?.[id]?.value?.properties || []) const excludeProperties = ['date', 'select', 'multi_select', 'person'] @@ -108,6 +117,7 @@ export default async function getPageProperties(id, block, schema, authToken, ta properties.slug += '.html' } } + // 密码字段md5 properties.password = properties.password ? md5(properties.slug + properties.password) : '' return properties } diff --git a/next-sitemap.config.js b/next-sitemap.config.js index a094e809..29e1ca67 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,5 +1,8 @@ const BLOG = require('./blog.config') +/** + * 通常没啥用,sitemap交给 /pages/sitemap.xml.js 动态生成 + */ module.exports = { siteUrl: BLOG.LINK, changefreq: 'daily', From 52495e020074f2e052f64772d0f478abcce0270c Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Wed, 1 Nov 2023 18:40:00 +0800 Subject: [PATCH 03/48] =?UTF-8?q?=E9=83=A8=E5=88=86=E9=85=8D=E7=BD=AEsiteC?= =?UTF-8?q?onfig=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Artalk.js | 3 +- components/Comment.js | 2 +- components/CommonHead.js | 40 ++++++++-------- lib/config.js | 49 ++++++++++++++++++++ lib/global.js | 5 +- lib/notion/getNotionConfig.js | 4 +- lib/notion/getNotionData.js | 4 +- pages/404.js | 5 +- pages/[prefix]/index.js | 3 +- pages/archive/index.js | 5 +- pages/category/[category]/index.js | 5 +- pages/category/[category]/page/[page].js | 5 +- pages/category/index.js | 5 +- pages/index.js | 24 +++++----- pages/page/[page].js | 5 +- pages/search/[keyword]/index.js | 5 +- pages/search/[keyword]/page/[page].js | 5 +- pages/search/index.js | 5 +- pages/tag/[tag]/index.js | 5 +- pages/tag/[tag]/page/[page].js | 5 +- pages/tag/index.js | 5 +- themes/example/components/BlogPostCard.js | 3 +- themes/example/components/Footer.js | 3 +- themes/example/components/Header.js | 5 +- themes/example/components/Title.js | 7 +-- themes/fukasawa/components/AsideLeft.js | 8 ++-- themes/fukasawa/components/Logo.js | 4 +- themes/fukasawa/components/SiteInfo.js | 3 +- themes/gitbook/components/Footer.js | 5 +- themes/gitbook/components/InfoCard.js | 6 +-- themes/gitbook/components/LogoBar.js | 6 +-- themes/heo/components/ArticleCopyright.js | 3 +- themes/heo/components/Footer.js | 4 +- themes/heo/components/InfoCard.js | 6 +-- themes/heo/components/Logo.js | 6 +-- themes/heo/components/NavBar.js | 4 +- themes/heo/components/SideBar.js | 4 +- themes/heo/index.js | 4 +- themes/hexo/components/ArticleCopyright.js | 11 +++-- themes/hexo/components/Footer.js | 4 +- themes/hexo/components/Hero.js | 3 +- themes/hexo/components/InfoCard.js | 5 +- themes/hexo/components/Logo.js | 4 +- themes/hexo/components/SideBar.js | 4 +- themes/hexo/index.js | 10 ++-- themes/matery/components/ArticleCopyright.js | 3 +- themes/matery/components/Footer.js | 4 +- themes/matery/components/Hero.js | 3 +- themes/matery/components/InfoCard.js | 6 ++- themes/matery/components/Logo.js | 4 +- themes/matery/components/SideBar.js | 8 ++-- themes/matery/index.js | 3 +- themes/medium/components/ArticleInfo.js | 5 +- themes/medium/components/Footer.js | 3 +- themes/medium/components/InfoCard.js | 5 +- themes/medium/components/LogoBar.js | 4 +- themes/medium/index.js | 5 +- themes/nav/components/Footer.js | 6 +-- themes/nav/components/InfoCard.js | 6 +-- themes/nav/components/LogoBar.js | 5 +- themes/next/components/ArticleDetail.js | 3 +- themes/next/components/Footer.js | 4 +- themes/next/components/InfoCard.js | 6 +-- themes/next/components/Logo.js | 7 +-- themes/next/index.js | 5 +- themes/nobelium/components/BlogListScroll.js | 7 +-- themes/nobelium/components/Footer.js | 3 +- themes/nobelium/components/Nav.js | 7 +-- themes/nobelium/components/Title.js | 8 ++-- themes/plog/components/BlogListScroll.js | 3 +- themes/plog/components/Footer.js | 3 +- themes/plog/components/LogoBar.js | 7 +-- themes/plog/components/Nav.js | 7 +-- themes/plog/components/SlideOvers.js | 3 +- themes/plog/components/Title.js | 8 ++-- themes/simple/components/ArticleInfo.js | 4 +- themes/simple/components/BlogItem.js | 3 +- themes/simple/components/Footer.js | 3 +- themes/simple/components/Header.js | 8 ++-- themes/simple/components/Title.js | 8 ++-- 80 files changed, 293 insertions(+), 200 deletions(-) create mode 100644 lib/config.js diff --git a/components/Artalk.js b/components/Artalk.js index 0da7734f..9f047a2f 100644 --- a/components/Artalk.js +++ b/components/Artalk.js @@ -1,4 +1,5 @@ import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' import { loadExternalResource } from '@/lib/utils' // import { loadExternalResource } from '@/lib/utils' import { useEffect } from 'react' @@ -19,7 +20,7 @@ const Artalk = ({ siteInfo }) => { locale: BLOG.LANG, // pageKey: '/post/1', // 固定链接 (留空自动获取) // pageTitle: '关于引入 Artalk 的这档子事', // 页面标题 (留空自动获取) - site: siteInfo?.title // 你的站点名 + site: siteConfig('TITLE') // 你的站点名 }) }, []) return ( diff --git a/components/Comment.js b/components/Comment.js index 6be4bc64..9359ed36 100644 --- a/components/Comment.js +++ b/components/Comment.js @@ -86,7 +86,7 @@ const Comment = ({ siteInfo, frontMatter, className }) => {
{BLOG.COMMENT_ARTALK_SERVER && (
- +
)} {BLOG.COMMENT_TWIKOO_ENV_ID && (
diff --git a/components/CommonHead.js b/components/CommonHead.js index 24bfae69..752a65bf 100644 --- a/components/CommonHead.js +++ b/components/CommonHead.js @@ -1,34 +1,34 @@ -import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' import Head from 'next/head' const CommonHead = ({ meta, children }) => { - let url = BLOG?.PATH?.length ? `${BLOG.LINK}/${BLOG.SUB_PATH}` : BLOG.LINK + let url = siteConfig('PATH')?.length ? `${siteConfig('LINK')}/${siteConfig('SUB_PATH')}` : siteConfig('LINK') let image if (meta) { url = `${url}/${meta.slug}` image = meta.image || '/bg_image.jpg' } - const title = meta?.title || BLOG.TITLE - const description = meta?.description || BLOG.DESCRIPTION + const title = meta?.title || siteConfig('TITLE') + const description = meta?.description || siteConfig('DESCRIPTION') const type = meta?.type || 'website' - const keywords = meta?.tags || BLOG.KEYWORDS - const lang = BLOG.LANG.replace('-', '_') // Facebook OpenGraph 要 zh_CN 這樣的格式才抓得到語言 - const category = meta?.category || BLOG.KEYWORDS || '軟體科技' // section 主要是像是 category 這樣的分類,Facebook 用這個來抓連結的分類 + const keywords = meta?.tags || siteConfig('KEYWORDS') + const lang = siteConfig('LANG').replace('-', '_') // Facebook OpenGraph 要 zh_CN 這樣的格式才抓得到語言 + const category = meta?.category || siteConfig('KEYWORDS') || '軟體科技' // section 主要是像是 category 這樣的分類,Facebook 用這個來抓連結的分類 return ( {title} - + - {BLOG.SEO_GOOGLE_SITE_VERIFICATION && ( + {siteConfig('SEO_GOOGLE_SITE_VERIFICATION') && ( )} - {BLOG.SEO_BAIDU_SITE_VERIFICATION && ()} + {siteConfig('SEO_BAIDU_SITE_VERIFICATION') && ()} @@ -36,33 +36,33 @@ const CommonHead = ({ meta, children }) => { - + - {BLOG.COMMENT_WEBMENTION.ENABLE && ( + {siteConfig('COMMENT_WEBMENTION').ENABLE && ( <> - - + + )} - {BLOG.COMMENT_WEBMENTION.ENABLE && BLOG.COMMENT_WEBMENTION.AUTH !== '' && ( - + {siteConfig('COMMENT_WEBMENTION').ENABLE && siteConfig('COMMENT_WEBMENTION').AUTH !== '' && ( + )} - {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } + {JSON.parse(siteConfig('ANALYTICS_BUSUANZI_ENABLE')) && } {meta?.type === 'Post' && ( <> - + - + )} {children} diff --git a/lib/config.js b/lib/config.js new file mode 100644 index 00000000..62b5149b --- /dev/null +++ b/lib/config.js @@ -0,0 +1,49 @@ +'use client' + +import BLOG from '@/blog.config' +import { useGlobal } from './global' + +/** + * 读取配置 + * @param {*} key + * @returns + */ +export const siteConfig = (key) => { + let global = null + try { + // eslint-disable-next-line react-hooks/rules-of-hooks + global = useGlobal() + } catch (error) {} + + // 首先 配置最优先读取NOTION中的表格配置 + let val = null + let siteInfo = null + + if (global) { + val = global.NOTION_CONFIG?.[key] + siteInfo = global.siteInfo + console.log('当前变量', key, val) + } + + if (!val) { + // 这里针对部分key做一些兼容处理 + switch (key) { + case 'HOME_BANNER_IMAGE': + val = siteInfo?.pageCover // 封面图取Notion的封面 + break + case 'AVATAR': + val = siteInfo?.icon // 封面图取Notion的封面 + break + case 'TITLE': + val = siteConfig('TITLE') // 标题取Notion中的标题 + break + } + } + + // 其次 NOTION没有找到配置,则会读取blog.config.js文件 + if (!val) { + val = BLOG[key] + } + console.log('配置', key, val) + return val +} diff --git a/lib/global.js b/lib/global.js index c290a9e0..d1fc4142 100644 --- a/lib/global.js +++ b/lib/global.js @@ -1,10 +1,10 @@ import { generateLocaleDict, initLocale } from './lang' import { createContext, useContext, useEffect, useState } from 'react' import { useRouter } from 'next/router' -import BLOG from '@/blog.config' import { THEMES, initDarkMode } from '@/themes/theme' import NProgress from 'nprogress' import { getQueryVariable, isBrowser } from './utils' +import BLOG from '@/blog.config' const GlobalContext = createContext() @@ -15,7 +15,7 @@ const GlobalContext = createContext() * @constructor */ export function GlobalContextProvider(props) { - const { children, siteInfo, categoryOptions, tagOptions } = props + const { children, siteInfo, categoryOptions, tagOptions, NOTION_CONFIG } = props const router = useRouter() const [lang, updateLang] = useState(BLOG.LANG) // 默认语言 const [locale, updateLocale] = useState(generateLocaleDict(BLOG.LANG)) // 默认语言 @@ -68,6 +68,7 @@ export function GlobalContextProvider(props) { return ( { - const { siteInfo } = useGlobal() - const meta = { title: `${props?.siteInfo?.title} | 页面找不到啦`, image: siteInfo?.pageCover } + const meta = { title: `${siteConfig('TITLE')} | 页面找不到啦`, image: siteConfig('HOME_BANNER_IMAGE') } props = { ...props, meta } diff --git a/pages/[prefix]/index.js b/pages/[prefix]/index.js index 6fa5d47b..b350fb18 100644 --- a/pages/[prefix]/index.js +++ b/pages/[prefix]/index.js @@ -10,6 +10,7 @@ import { getLayoutByTheme } from '@/themes/theme' import md5 from 'js-md5' import { isBrowser } from '@/lib/utils' import { uploadDataToAlgolia } from '@/lib/algolia' +import { siteConfig } from '@/lib/config' /** * 根据notion的slug访问页面 @@ -66,7 +67,7 @@ const Slug = props => { }, [post]) const meta = { - title: post ? `${post?.title} | ${siteInfo?.title}` : `${props?.siteInfo?.title || BLOG.TITLE} | loading`, + title: post ? `${post?.title} | ${siteConfig('TITLE')}` : `${props?.siteConfig('TITLE') || BLOG.TITLE} | loading`, description: post?.summary, type: post?.type, slug: post?.slug, diff --git a/pages/archive/index.js b/pages/archive/index.js index 106ad7d2..3726291d 100644 --- a/pages/archive/index.js +++ b/pages/archive/index.js @@ -6,6 +6,7 @@ import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' import { isBrowser } from '@/lib/utils' import { formatDateFmt } from '@/lib/formatDate' +import { siteConfig } from '@/lib/config' const ArchiveIndex = props => { const { siteInfo } = props @@ -29,8 +30,8 @@ const ArchiveIndex = props => { }, []) const meta = { - title: `${locale.NAV.ARCHIVE} | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${locale.NAV.ARCHIVE} | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'archive', type: 'website' diff --git a/pages/category/[category]/index.js b/pages/category/[category]/index.js index 03cd4fbd..a2c30722 100644 --- a/pages/category/[category]/index.js +++ b/pages/category/[category]/index.js @@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 分类页 @@ -19,9 +20,9 @@ export default function Category(props) { const meta = { title: `${props.category} | ${locale.COMMON.CATEGORY} | ${ - siteInfo?.title || '' + siteConfig('TITLE') || '' }`, - description: siteInfo?.description, + description: siteConfig('HOME_BANNER_IMAGE'), slug: 'category/' + props.category, image: siteInfo?.pageCover, type: 'website' diff --git a/pages/category/[category]/page/[page].js b/pages/category/[category]/page/[page].js index 9174e117..8a6cccc8 100644 --- a/pages/category/[category]/page/[page].js +++ b/pages/category/[category]/page/[page].js @@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 分类页 @@ -19,9 +20,9 @@ export default function Category(props) { const meta = { title: `${props.category} | ${locale.COMMON.CATEGORY} | ${ - siteInfo?.title || '' + siteConfig('TITLE') || '' }`, - description: siteInfo?.description, + description: siteConfig('HOME_BANNER_IMAGE'), slug: 'category/' + props.category, image: siteInfo?.pageCover, type: 'website' diff --git a/pages/category/index.js b/pages/category/index.js index b4872000..8f6d98bc 100644 --- a/pages/category/index.js +++ b/pages/category/index.js @@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 分类首页 @@ -18,8 +19,8 @@ export default function Category(props) { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${locale.COMMON.CATEGORY} | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${locale.COMMON.CATEGORY} | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'category', type: 'website' diff --git a/pages/index.js b/pages/index.js index 328ece1e..ac72c1b5 100644 --- a/pages/index.js +++ b/pages/index.js @@ -5,6 +5,7 @@ import { generateRss } from '@/lib/rss' import { generateRobotsTxt } from '@/lib/robots.txt' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 首页布局 @@ -14,7 +15,15 @@ import { getLayoutByTheme } from '@/themes/theme' const Index = props => { // 根据页面路径加载不同Layout文件 const Layout = getLayoutByTheme(useRouter()) - return + + const meta = { + title: `${siteConfig('TITLE')} | ${siteConfig('BIO')}`, + description: siteConfig('DESCRIPTION'), + image: siteConfig('HOME_BANNER_IMAGE'), + slug: '', + type: 'website' + } + return } /** @@ -25,16 +34,8 @@ export async function getStaticProps() { const from = 'index' const props = await getGlobalData({ from }) - const { siteInfo } = props props.posts = props.allPages?.filter(page => page.type === 'Post' && page.status === 'Published') - const meta = { - title: `${siteInfo?.title} | ${siteInfo?.description}`, - description: siteInfo?.description, - image: siteInfo?.pageCover, - slug: '', - type: 'website' - } // 处理分页 if (BLOG.POST_LIST_STYLE === 'scroll') { // 滚动列表默认给前端返回所有数据 @@ -65,10 +66,7 @@ export async function getStaticProps() { delete props.allPages return { - props: { - meta, - ...props - }, + props, revalidate: parseInt(BLOG.NEXT_REVALIDATE_SECOND) } } diff --git a/pages/page/[page].js b/pages/page/[page].js index 02b847a8..131feb45 100644 --- a/pages/page/[page].js +++ b/pages/page/[page].js @@ -3,6 +3,7 @@ import { getPostBlocks } from '@/lib/notion' import { getGlobalData } from '@/lib/notion/getNotionData' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 文章列表分页 @@ -16,8 +17,8 @@ const Page = props => { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${props?.page} | Page | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${props?.page} | Page | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'page/' + props.page, type: 'website' diff --git a/pages/search/[keyword]/index.js b/pages/search/[keyword]/index.js index 042bbf85..bc2514a1 100644 --- a/pages/search/[keyword]/index.js +++ b/pages/search/[keyword]/index.js @@ -4,6 +4,7 @@ import { getDataFromCache } from '@/lib/cache/cache_manager' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' const Index = props => { const { keyword, siteInfo } = props @@ -13,8 +14,8 @@ const Index = props => { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteInfo?.title}`, - description: siteInfo?.title, + title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteConfig('TITLE')}`, + description: siteConfig('TITLE'), image: siteInfo?.pageCover, slug: 'search/' + (keyword || ''), type: 'website' diff --git a/pages/search/[keyword]/page/[page].js b/pages/search/[keyword]/page/[page].js index 20240f19..c5c4aeb8 100644 --- a/pages/search/[keyword]/page/[page].js +++ b/pages/search/[keyword]/page/[page].js @@ -4,6 +4,7 @@ import { getDataFromCache } from '@/lib/cache/cache_manager' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' const Index = props => { const { keyword, siteInfo } = props @@ -13,8 +14,8 @@ const Index = props => { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteInfo?.title}`, - description: siteInfo?.title, + title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteConfig('TITLE')}`, + description: siteConfig('TITLE'), image: siteInfo?.pageCover, slug: 'search/' + (keyword || ''), type: 'website' diff --git a/pages/search/index.js b/pages/search/index.js index 22061cbd..31d09af3 100644 --- a/pages/search/index.js +++ b/pages/search/index.js @@ -3,6 +3,7 @@ import { useGlobal } from '@/lib/global' import { useRouter } from 'next/router' import BLOG from '@/blog.config' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 搜索路由 @@ -34,8 +35,8 @@ const Search = props => { } const meta = { - title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'search', type: 'website' diff --git a/pages/tag/[tag]/index.js b/pages/tag/[tag]/index.js index bd9f7529..f12cdc41 100644 --- a/pages/tag/[tag]/index.js +++ b/pages/tag/[tag]/index.js @@ -3,6 +3,7 @@ import { getGlobalData } from '@/lib/notion/getNotionData' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 标签下的文章列表 @@ -17,8 +18,8 @@ const Tag = props => { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${tag} | ${locale.COMMON.TAGS} | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${tag} | ${locale.COMMON.TAGS} | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'tag/' + tag, type: 'website' diff --git a/pages/tag/[tag]/page/[page].js b/pages/tag/[tag]/page/[page].js index 2eaef518..c708793b 100644 --- a/pages/tag/[tag]/page/[page].js +++ b/pages/tag/[tag]/page/[page].js @@ -3,6 +3,7 @@ import { getGlobalData } from '@/lib/notion/getNotionData' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' const Tag = props => { const { locale } = useGlobal() @@ -12,8 +13,8 @@ const Tag = props => { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${tag} | ${locale.COMMON.TAGS} | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${tag} | ${locale.COMMON.TAGS} | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'tag/' + tag, type: 'website' diff --git a/pages/tag/index.js b/pages/tag/index.js index 54dab9a4..cb6db4da 100644 --- a/pages/tag/index.js +++ b/pages/tag/index.js @@ -3,6 +3,7 @@ import { useGlobal } from '@/lib/global' import BLOG from '@/blog.config' import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' +import { siteConfig } from '@/lib/config' /** * 标签首页 @@ -17,8 +18,8 @@ const TagIndex = props => { const Layout = getLayoutByTheme(useRouter()) const meta = { - title: `${locale.COMMON.TAGS} | ${siteInfo?.title}`, - description: siteInfo?.description, + title: `${locale.COMMON.TAGS} | ${siteConfig('TITLE')}`, + description: siteConfig('HOME_BANNER_IMAGE'), image: siteInfo?.pageCover, slug: 'tag', type: 'website' diff --git a/themes/example/components/BlogPostCard.js b/themes/example/components/BlogPostCard.js index faf1753d..fb91a307 100644 --- a/themes/example/components/BlogPostCard.js +++ b/themes/example/components/BlogPostCard.js @@ -3,6 +3,7 @@ import CONFIG from '../config' import Link from 'next/link' import TwikooCommentCount from '@/components/TwikooCommentCount' import LazyImage from '@/components/LazyImage' +import { siteConfig } from '@/lib/config' const BlogPostCard = ({ post }) => { const showPageCover = CONFIG.POST_LIST_COVER && post?.pageCoverThumbnail @@ -18,7 +19,7 @@ const BlogPostCard = ({ post }) => {
- by {BLOG.AUTHOR} on {post.date?.start_date || post.createdTime} + by {siteConfig('AUTHOR')} on {post.date?.start_date || post.createdTime} | {post.category} diff --git a/themes/example/components/Footer.js b/themes/example/components/Footer.js index 09af18fe..26c1ae74 100644 --- a/themes/example/components/Footer.js +++ b/themes/example/components/Footer.js @@ -1,5 +1,6 @@ import BLOG from '@/blog.config' import DarkModeButton from '@/components/DarkModeButton' +import { siteConfig } from '@/lib/config' export const Footer = (props) => { const d = new Date() @@ -15,7 +16,7 @@ export const Footer = (props) => {
-
©{`${copyrightDate}`} {BLOG.AUTHOR}. All rights reserved.
+
©{`${copyrightDate}`} {siteConfig('AUTHOR')}. All rights reserved.
{/* 右侧链接 */} {/* Privacy Policy */} diff --git a/themes/example/components/Header.js b/themes/example/components/Header.js index 0cd85268..2ec1e27b 100644 --- a/themes/example/components/Header.js +++ b/themes/example/components/Header.js @@ -1,12 +1,11 @@ import Link from 'next/link' +import { siteConfig } from '@/lib/config' /** * 网站顶部 * @returns */ export const Header = (props) => { - const { siteInfo } = props - return (
@@ -14,7 +13,7 @@ export const Header = (props) => { href='/' className="py-6 w-full text-center md:text-left md:w-auto text-gray-dark no-underline flex justify-center items-center"> - {siteInfo?.title} + {siteConfig('TITLE')}
{/* 右侧文字 */} diff --git a/themes/example/components/Title.js b/themes/example/components/Title.js index e57e2347..08fd67f1 100644 --- a/themes/example/components/Title.js +++ b/themes/example/components/Title.js @@ -1,4 +1,5 @@ import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' /** * 标题栏 @@ -6,9 +7,9 @@ import BLOG from '@/blog.config' * @returns */ export const Title = (props) => { - const { siteInfo, post } = props - const title = post?.title || siteInfo?.description - const description = post?.description || BLOG.AUTHOR + const { post } = props + const title = post?.title || siteConfig('HOME_BANNER_IMAGE') + const description = post?.description || siteConfig('AUTHOR') return

{title}

diff --git a/themes/fukasawa/components/AsideLeft.js b/themes/fukasawa/components/AsideLeft.js index bf6edb45..131e5f31 100644 --- a/themes/fukasawa/components/AsideLeft.js +++ b/themes/fukasawa/components/AsideLeft.js @@ -12,9 +12,7 @@ import SocialButton from './SocialButton' import { useFukasawaGlobal } from '..' import CONFIG from '@/themes/fukasawa/config' import { AdSlot } from '@/components/GoogleAdsense' - -// import { debounce } from 'lodash' -// import { useEffect } from 'react' +import { siteConfig } from '@/lib/config' /** * 侧边栏 @@ -22,7 +20,7 @@ import { AdSlot } from '@/components/GoogleAdsense' * @returns */ function AsideLeft(props) { - const { tagOptions, currentTag, categoryOptions, currentCategory, post, slot, siteInfo, notice } = props + const { tagOptions, currentTag, categoryOptions, currentCategory, post, slot, notice } = props const router = useRouter() const { isCollapsed, setIsCollapse } = useFukasawaGlobal() // 折叠侧边栏 @@ -65,7 +63,7 @@ function AsideLeft(props) {
- {siteInfo?.description} + {siteConfig('HOME_BANNER_IMAGE')}
diff --git a/themes/fukasawa/components/Logo.js b/themes/fukasawa/components/Logo.js index 3b6720fb..1b28e1ec 100644 --- a/themes/fukasawa/components/Logo.js +++ b/themes/fukasawa/components/Logo.js @@ -1,13 +1,13 @@ import Link from 'next/link' +import { siteConfig } from '@/lib/config' const Logo = props => { - const { siteInfo } = props return (
- {siteInfo?.title} + {siteConfig('TITLE')}
); diff --git a/themes/fukasawa/components/SiteInfo.js b/themes/fukasawa/components/SiteInfo.js index 3a18bcd1..d4b25b54 100644 --- a/themes/fukasawa/components/SiteInfo.js +++ b/themes/fukasawa/components/SiteInfo.js @@ -1,4 +1,5 @@ import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' function SiteInfo ({ title }) { const d = new Date() @@ -14,7 +15,7 @@ function SiteInfo ({ title }) {
- © {`${copyrightDate}`} {BLOG.AUTHOR}.
+ © {`${copyrightDate}`} {siteConfig('AUTHOR')}.
{BLOG.BEI_AN && <> {BLOG.BEI_AN}
} diff --git a/themes/gitbook/components/Footer.js b/themes/gitbook/components/Footer.js index fb1d339c..09cb9daf 100644 --- a/themes/gitbook/components/Footer.js +++ b/themes/gitbook/components/Footer.js @@ -1,5 +1,6 @@ import React from 'react' import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' const Footer = ({ siteInfo }) => { const d = new Date() @@ -18,7 +19,7 @@ const Footer = ({ siteInfo }) => {
- + © {`${copyrightDate}`}
@@ -30,7 +31,7 @@ const Footer = ({ siteInfo }) => {
-

{siteInfo?.title}

+

{siteConfig('TITLE')}

) diff --git a/themes/gitbook/components/InfoCard.js b/themes/gitbook/components/InfoCard.js index 13fe31c8..6687aa04 100644 --- a/themes/gitbook/components/InfoCard.js +++ b/themes/gitbook/components/InfoCard.js @@ -1,17 +1,17 @@ import BLOG from '@/blog.config' import LazyImage from '@/components/LazyImage' import Router from 'next/router' -import React from 'react' import SocialButton from './SocialButton' +import { siteConfig } from '@/lib/config' const InfoCard = (props) => { const { siteInfo } = props return
{ Router.push('/about') }}> - +
-
{BLOG.AUTHOR}
+
{siteConfig('AUTHOR')}
{BLOG.BIO}
diff --git a/themes/gitbook/components/LogoBar.js b/themes/gitbook/components/LogoBar.js index 70c96b46..e0f7b4cb 100644 --- a/themes/gitbook/components/LogoBar.js +++ b/themes/gitbook/components/LogoBar.js @@ -1,7 +1,7 @@ -import BLOG from '@/blog.config' import LazyImage from '@/components/LazyImage' import { useGitBookGlobal } from '@/themes/gitbook' import Link from 'next/link' +import { siteConfig } from '@/lib/config' /** * Logo区域 @@ -21,8 +21,8 @@ export default function LogoBar(props) {
- - {siteInfo?.title} + + {siteConfig('TITLE')}
) diff --git a/themes/heo/components/ArticleCopyright.js b/themes/heo/components/ArticleCopyright.js index 78500ddf..740fdc1c 100644 --- a/themes/heo/components/ArticleCopyright.js +++ b/themes/heo/components/ArticleCopyright.js @@ -4,6 +4,7 @@ import Link from 'next/link' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import CONFIG from '../config' +import { siteConfig } from '@/lib/config' export default function ArticleCopyright () { const router = useRouter() @@ -24,7 +25,7 @@ export default function ArticleCopyright () {
  • {locale.COMMON.AUTHOR}: - {BLOG.AUTHOR} + {siteConfig('AUTHOR')}
  • diff --git a/themes/heo/components/Footer.js b/themes/heo/components/Footer.js index 772ade19..4899a544 100644 --- a/themes/heo/components/Footer.js +++ b/themes/heo/components/Footer.js @@ -1,7 +1,7 @@ import React from 'react' import BLOG from '@/blog.config' import SocialButton from './SocialButton' -// import DarkModeButton from '@/components/DarkModeButton' +import { siteConfig } from '@/lib/config' const Footer = ({ title }) => { const d = new Date() @@ -34,7 +34,7 @@ const Footer = ({ title }) => { {/* 页脚 */} -
    +
  • ) } diff --git a/themes/nobelium/components/BlogListScroll.js b/themes/nobelium/components/BlogListScroll.js index d3d91abb..90d1d0e1 100644 --- a/themes/nobelium/components/BlogListScroll.js +++ b/themes/nobelium/components/BlogListScroll.js @@ -1,9 +1,10 @@ import BLOG from '@/blog.config' import { useGlobal } from '@/lib/global' import Link from 'next/link' -import React from 'react' import throttle from 'lodash.throttle' import { deepClone } from '@/lib/utils' +import { siteConfig } from '@/lib/config' +import { useEffect } from 'react' export const BlogListScroll = props => { const { posts } = props @@ -36,7 +37,7 @@ export const BlogListScroll = props => { } }, 500)) - React.useEffect(() => { + useEffect(() => { window.addEventListener('scroll', scrollTrigger) return () => { @@ -57,7 +58,7 @@ export const BlogListScroll = props => {
    - by {BLOG.AUTHOR} on {p.date?.start_date || p.createdTime} + by {siteConfig('AUTHOR')} on {p.date?.start_date || p.createdTime} | {p.category} | diff --git a/themes/nobelium/components/Footer.js b/themes/nobelium/components/Footer.js index 6b4b7857..3b4044a8 100644 --- a/themes/nobelium/components/Footer.js +++ b/themes/nobelium/components/Footer.js @@ -1,6 +1,7 @@ import BLOG from '@/blog.config' import DarkModeButton from '@/components/DarkModeButton' import Vercel from '@/components/Vercel' +import { siteConfig } from '@/lib/config' export const Footer = (props) => { const d = new Date() @@ -25,7 +26,7 @@ export const Footer = (props) => {

    - © {BLOG.AUTHOR} {copyrightDate} + © {siteConfig('AUTHOR')} {copyrightDate}

    diff --git a/themes/nobelium/components/Nav.js b/themes/nobelium/components/Nav.js index 7e6c12ac..73df49a3 100644 --- a/themes/nobelium/components/Nav.js +++ b/themes/nobelium/components/Nav.js @@ -10,6 +10,7 @@ import { MenuItemCollapse } from './MenuItemCollapse' import LazyImage from '@/components/LazyImage' import RandomPostButton from './RandomPostButton' import SearchButton from './SearchButton' +import { siteConfig } from '@/lib/config' const Nav = props => { const { navBarTitle, fullWidth, siteInfo } = props @@ -48,7 +49,7 @@ const Nav = props => {
    {/* */} {CONFIG.NAV_NOTION_ICON - ? + ? : }
    @@ -62,8 +63,8 @@ const Nav = props => { ) : (

    - {siteInfo?.title} - {/* ,{' '}{siteInfo?.description} */} + {siteConfig('TITLE')} + {/* ,{' '}{siteConfig('HOME_BANNER_IMAGE')} */}

    )}
    diff --git a/themes/nobelium/components/Title.js b/themes/nobelium/components/Title.js index e57e2347..a1512af2 100644 --- a/themes/nobelium/components/Title.js +++ b/themes/nobelium/components/Title.js @@ -1,4 +1,4 @@ -import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' /** * 标题栏 @@ -6,9 +6,9 @@ import BLOG from '@/blog.config' * @returns */ export const Title = (props) => { - const { siteInfo, post } = props - const title = post?.title || siteInfo?.description - const description = post?.description || BLOG.AUTHOR + const { post } = props + const title = post?.title || siteConfig('HOME_BANNER_IMAGE') + const description = post?.description || siteConfig('AUTHOR') return

    {title}

    diff --git a/themes/plog/components/BlogListScroll.js b/themes/plog/components/BlogListScroll.js index 157e80e4..809451f6 100644 --- a/themes/plog/components/BlogListScroll.js +++ b/themes/plog/components/BlogListScroll.js @@ -3,6 +3,7 @@ import { useGlobal } from '@/lib/global' import Link from 'next/link' import React from 'react' import throttle from 'lodash.throttle' +import { siteConfig } from '@/lib/config' export const BlogListScroll = props => { const { posts } = props @@ -56,7 +57,7 @@ export const BlogListScroll = props => {
    - by {BLOG.AUTHOR} on {p.date?.start_date || p.createdTime} + by {siteConfig('AUTHOR')} on {p.date?.start_date || p.createdTime} | {p.category} | diff --git a/themes/plog/components/Footer.js b/themes/plog/components/Footer.js index 2a6bdcb9..d53de2f3 100644 --- a/themes/plog/components/Footer.js +++ b/themes/plog/components/Footer.js @@ -1,5 +1,6 @@ import BLOG from '@/blog.config' import Vercel from '@/components/Vercel' +import { siteConfig } from '@/lib/config' export const Footer = (props) => { const d = new Date() @@ -15,7 +16,7 @@ export const Footer = (props) => { return
    -
    © {BLOG.AUTHOR} {copyrightDate}
    +
    © {siteConfig('AUTHOR')} {copyrightDate}
    diff --git a/themes/plog/components/LogoBar.js b/themes/plog/components/LogoBar.js index 07539f2f..070b45ae 100644 --- a/themes/plog/components/LogoBar.js +++ b/themes/plog/components/LogoBar.js @@ -3,6 +3,7 @@ import LazyImage from '@/components/LazyImage' import Link from 'next/link' import CONFIG from '../config' import { SvgIcon } from './SvgIcon' +import { siteConfig } from '@/lib/config' /** * logo文字栏 @@ -16,7 +17,7 @@ export default function LogoBar(props) {
    {CONFIG.NAV_NOTION_ICON - ? + ? : }
    @@ -30,8 +31,8 @@ export default function LogoBar(props) { ) : (

    - {siteInfo?.title} - {' '}{siteInfo?.description} + {siteConfig('TITLE')} + {' '}{siteConfig('HOME_BANNER_IMAGE')}

    )}
    diff --git a/themes/plog/components/Nav.js b/themes/plog/components/Nav.js index 401f0d49..f57accac 100644 --- a/themes/plog/components/Nav.js +++ b/themes/plog/components/Nav.js @@ -8,11 +8,12 @@ import { MenuItemDrop } from './MenuItemDrop' import Collapse from '@/components/Collapse' import { MenuItemCollapse } from './MenuItemCollapse' import LazyImage from '@/components/LazyImage' +import { siteConfig } from '@/lib/config' const Header = props => { const { fullWidth, siteInfo } = props - const title = siteInfo?.title + const title = siteConfig('TITLE') return
    ) diff --git a/themes/simple/components/Title.js b/themes/simple/components/Title.js index e57e2347..a1512af2 100644 --- a/themes/simple/components/Title.js +++ b/themes/simple/components/Title.js @@ -1,4 +1,4 @@ -import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' /** * 标题栏 @@ -6,9 +6,9 @@ import BLOG from '@/blog.config' * @returns */ export const Title = (props) => { - const { siteInfo, post } = props - const title = post?.title || siteInfo?.description - const description = post?.description || BLOG.AUTHOR + const { post } = props + const title = post?.title || siteConfig('HOME_BANNER_IMAGE') + const description = post?.description || siteConfig('AUTHOR') return

    {title}

    From 47b82d12bd2dfd9230686ac33af6294123765447 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Wed, 1 Nov 2023 18:41:13 +0800 Subject: [PATCH 04/48] =?UTF-8?q?=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/config.js | 3 +++ themes/example/components/Title.js | 1 - themes/medium/components/ArticleInfo.js | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/config.js b/lib/config.js index 62b5149b..b6c99afb 100644 --- a/lib/config.js +++ b/lib/config.js @@ -5,6 +5,9 @@ import { useGlobal } from './global' /** * 读取配置 + * 1. 优先读取NotionConfig表 + * 2. 其次读取环境变量 + * 3. 再读取blog.config.js文件 * @param {*} key * @returns */ diff --git a/themes/example/components/Title.js b/themes/example/components/Title.js index 08fd67f1..a1512af2 100644 --- a/themes/example/components/Title.js +++ b/themes/example/components/Title.js @@ -1,4 +1,3 @@ -import BLOG from '@/blog.config' import { siteConfig } from '@/lib/config' /** diff --git a/themes/medium/components/ArticleInfo.js b/themes/medium/components/ArticleInfo.js index 9b0ea2b9..12c189db 100644 --- a/themes/medium/components/ArticleInfo.js +++ b/themes/medium/components/ArticleInfo.js @@ -1,4 +1,3 @@ -import BLOG from '@/blog.config' import LazyImage from '@/components/LazyImage' import Link from 'next/link' import { siteConfig } from '@/lib/config' From 3e58c6b637ab98ba15c0a014dbba783b1b6d76b1 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 1 Nov 2023 23:13:25 +0800 Subject: [PATCH 05/48] =?UTF-8?q?=E5=8A=A8=E6=80=81=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ExternalPlugins.js | 14 ++------ lib/config.js | 6 ++-- lib/global.js | 53 +++++++++++++++++------------- lib/lang.js | 2 +- lib/notion/getNotionConfig.js | 2 +- pages/_app.js | 5 ++- themes/hexo/components/Footer.js | 4 +-- themes/hexo/components/InfoCard.js | 2 +- 8 files changed, 43 insertions(+), 45 deletions(-) diff --git a/components/ExternalPlugins.js b/components/ExternalPlugins.js index 5b771fbb..c65836c4 100644 --- a/components/ExternalPlugins.js +++ b/components/ExternalPlugins.js @@ -2,17 +2,6 @@ import BLOG from 'blog.config' import dynamic from 'next/dynamic' import WebWhiz from './Webwhiz' -// import TwikooCommentCounter from '@/components/TwikooCommentCounter' -// import { DebugPanel } from '@/components/DebugPanel' -// import { ThemeSwitch } from '@/components/ThemeSwitch' -// import { Fireworks } from '@/components/Fireworks' -// import { Nest } from '@/components/Nest' -// import { FlutteringRibbon } from '@/components/FlutteringRibbon' -// import { Ribbon } from '@/components/Ribbon' -// import { Sakura } from '@/components/Sakura' -// import { StarrySky } from '@/components/StarrySky' -// import { Analytics } from '@vercel/analytics/react' - const TwikooCommentCounter = dynamic(() => import('@/components/TwikooCommentCounter'), { ssr: false }) const DebugPanel = dynamic(() => import('@/components/DebugPanel'), { ssr: false }) const ThemeSwitch = dynamic(() => import('@/components/ThemeSwitch'), { ssr: false }) @@ -33,8 +22,9 @@ const VConsole = dynamic(() => import('@/components/VConsole'), { ssr: false }) const CustomContextMenu = dynamic(() => import('@/components/CustomContextMenu'), { ssr: false }) const DisableCopy = dynamic(() => import('@/components/DisableCopy'), { ssr: false }) const AdBlockDetect = dynamic(() => import('@/components/AdBlockDetect'), { ssr: false }) + /** - * 各种第三方组件 + * 各种插件脚本 * @param {*} props * @returns */ diff --git a/lib/config.js b/lib/config.js index b6c99afb..ff931386 100644 --- a/lib/config.js +++ b/lib/config.js @@ -25,7 +25,7 @@ export const siteConfig = (key) => { if (global) { val = global.NOTION_CONFIG?.[key] siteInfo = global.siteInfo - console.log('当前变量', key, val) + // console.log('当前变量', key, val) } if (!val) { @@ -38,7 +38,7 @@ export const siteConfig = (key) => { val = siteInfo?.icon // 封面图取Notion的封面 break case 'TITLE': - val = siteConfig('TITLE') // 标题取Notion中的标题 + val = siteInfo?.title // 标题取Notion中的标题 break } } @@ -47,6 +47,6 @@ export const siteConfig = (key) => { if (!val) { val = BLOG[key] } - console.log('配置', key, val) + console.log('实际配置', key, val) return val } diff --git a/lib/global.js b/lib/global.js index d1fc4142..548b6d8c 100644 --- a/lib/global.js +++ b/lib/global.js @@ -2,33 +2,53 @@ import { generateLocaleDict, initLocale } from './lang' import { createContext, useContext, useEffect, useState } from 'react' import { useRouter } from 'next/router' import { THEMES, initDarkMode } from '@/themes/theme' -import NProgress from 'nprogress' -import { getQueryVariable, isBrowser } from './utils' + import BLOG from '@/blog.config' +import NProgress from 'nprogress' +import { isBrowser } from './utils' const GlobalContext = createContext() /** - * 全局变量Provider,包括语言本地化、样式主题、搜索词 + * 定义全局变量,包括语言、主题、深色模式、加载状态 * @param children * @returns {JSX.Element} * @constructor */ export function GlobalContextProvider(props) { const { children, siteInfo, categoryOptions, tagOptions, NOTION_CONFIG } = props + console.log('config', NOTION_CONFIG) const router = useRouter() - const [lang, updateLang] = useState(BLOG.LANG) // 默认语言 - const [locale, updateLocale] = useState(generateLocaleDict(BLOG.LANG)) // 默认语言 - const [theme, setTheme] = useState(BLOG.THEME) // 默认博客主题 - const [isDarkMode, updateDarkMode] = useState(BLOG.APPEARANCE === 'dark') // 默认深色模式 + const [lang, updateLang] = useState(NOTION_CONFIG.LANG || BLOG.LANG) // 默认语言 + const [locale, updateLocale] = useState(generateLocaleDict(NOTION_CONFIG.LANG || BLOG.LANG)) // 默认语言 + const [theme, setTheme] = useState(NOTION_CONFIG.THEME || BLOG.THEME) // 默认博客主题 + const [isDarkMode, updateDarkMode] = useState(NOTION_CONFIG.APPEARANCE || BLOG.APPEARANCE === 'dark') // 默认深色模式 const [onLoading, setOnLoading] = useState(false) // 抓取文章数据 + // 切换主题 + function switchTheme() { + const currentIndex = THEMES.indexOf(theme) + const newIndex = currentIndex < THEMES.length - 1 ? currentIndex + 1 : 0 + const newTheme = THEMES[newIndex] + const query = router.query + query.theme = newTheme + router.push({ pathname: router.pathname, query }) + return newTheme + } + useEffect(() => { initLocale(lang, locale, updateLang, updateLocale) initDarkMode(updateDarkMode) - initTheme() + checkThemeDOM() }, []) + // 加载默认主题 + // useEffect(() => { + // const queryTheme = getQueryVariable('theme') || theme + // setTheme(queryTheme) + // }, [router]) + + // 加载进度条 useEffect(() => { const handleStart = (url) => { NProgress.start() @@ -43,8 +63,6 @@ export function GlobalContextProvider(props) { NProgress.done() setOnLoading(false) } - const queryTheme = getQueryVariable('theme') || BLOG.THEME - setTheme(queryTheme) router.events.on('routeChangeStart', handleStart) router.events.on('routeChangeError', handleStop) router.events.on('routeChangeComplete', handleStop) @@ -55,22 +73,13 @@ export function GlobalContextProvider(props) { } }, [router]) - // 切换主题 - function switchTheme() { - const currentIndex = THEMES.indexOf(theme) - const newIndex = currentIndex < THEMES.length - 1 ? currentIndex + 1 : 0 - const newTheme = THEMES[newIndex] - const query = router.query - query.theme = newTheme - router.push({ pathname: router.pathname, query }) - return newTheme - } - return ( { +const checkThemeDOM = () => { if (isBrowser) { setTimeout(() => { const elements = document.querySelectorAll('[id^="theme-"]') diff --git a/lib/lang.js b/lib/lang.js index abc51354..d69da08f 100644 --- a/lib/lang.js +++ b/lib/lang.js @@ -65,7 +65,7 @@ export function generateLocaleDict(langString) { */ export function initLocale(lang, locale, changeLang, changeLocale) { if (isBrowser) { - const queryLang = getQueryVariable('lang') || loadLangFromCookies() || window.navigator.language + const queryLang = getQueryVariable('lang') || loadLangFromCookies() let currentLang = lang if (queryLang !== lang) { currentLang = queryLang diff --git a/lib/notion/getNotionConfig.js b/lib/notion/getNotionConfig.js index d5d51f51..d03eeaca 100644 --- a/lib/notion/getNotionConfig.js +++ b/lib/notion/getNotionConfig.js @@ -127,7 +127,7 @@ export async function getConfigMapFromConfigPage(allPages) { // 只导入生效的配置 if (config.enable) { - // console.log('[覆盖代码配置]', config.key) + console.log('[Notion配置]', config.key, config.value) notionConfig[config.key] = config.value } } diff --git a/pages/_app.js b/pages/_app.js index a16513b9..a19933cb 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -11,12 +11,11 @@ import { GlobalContextProvider } from '@/lib/global' import AOS from 'aos' import 'aos/dist/aos.css' // You can also use for styles -import dynamic from 'next/dynamic' import { isBrowser, loadExternalResource } from '@/lib/utils' import BLOG from '@/blog.config' - // 各种扩展插件 动画等 -const ExternalPlugins = dynamic(() => import('@/components/ExternalPlugins')) +import ExternalPlugins from '@/components/ExternalPlugins' +// const ExternalPlugins = dynamic(() => import('@/components/ExternalPlugins')) const MyApp = ({ Component, pageProps }) => { // 自定义样式css和js引入 diff --git a/themes/hexo/components/Footer.js b/themes/hexo/components/Footer.js index 3ccda463..ced637e9 100644 --- a/themes/hexo/components/Footer.js +++ b/themes/hexo/components/Footer.js @@ -26,8 +26,8 @@ const Footer = ({ title }) => { -

    {title} {BLOG.BIO && <>|} {BLOG.BIO}

    -

    Powered by NotionNext {BLOG.VERSION}.


    +

    {title} {siteConfig('BIO') && <>|} {siteConfig('BIO')}

    +

    Powered by NotionNext {siteConfig('VERSION')}.


    ) diff --git a/themes/hexo/components/InfoCard.js b/themes/hexo/components/InfoCard.js index 4f62a120..0676f8f7 100644 --- a/themes/hexo/components/InfoCard.js +++ b/themes/hexo/components/InfoCard.js @@ -26,7 +26,7 @@ export function InfoCard(props) {
    {siteConfig('AUTHOR')}
    -
    {BLOG.BIO}
    +
    {siteConfig('BIO')}
    From a6cc5a11f37c8e2232cf80050dbe300874ad15cd Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Thu, 2 Nov 2023 09:38:19 +0800 Subject: [PATCH 06/48] Notion_Config --- themes/hexo/components/Hero.js | 4 ++-- themes/matery/components/Hero.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/themes/hexo/components/Hero.js b/themes/hexo/components/Hero.js index b6a32b8f..f279f18e 100644 --- a/themes/hexo/components/Hero.js +++ b/themes/hexo/components/Hero.js @@ -4,7 +4,6 @@ import Typed from 'typed.js' import CONFIG from '../config' import NavButtonGroup from './NavButtonGroup' import { useGlobal } from '@/lib/global' -import BLOG from '@/blog.config' import LazyImage from '@/components/LazyImage' import { siteConfig } from '@/lib/config' @@ -21,13 +20,14 @@ const Hero = props => { const scrollToWrapper = () => { window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) } + const GREETING_WORDS = siteConfig('GREETING_WORDS').split(',') useEffect(() => { updateHeaderHeight() if (!typed && window && document.getElementById('typed')) { changeType( new Typed('#typed', { - strings: BLOG.GREETING_WORDS.split(','), + strings: GREETING_WORDS, typeSpeed: 200, backSpeed: 100, backDelay: 400, diff --git a/themes/matery/components/Hero.js b/themes/matery/components/Hero.js index bb8d65ff..5ca4d14d 100644 --- a/themes/matery/components/Hero.js +++ b/themes/matery/components/Hero.js @@ -3,7 +3,6 @@ import { useEffect, useState } from 'react' import Typed from 'typed.js' import CONFIG from '../config' import { useGlobal } from '@/lib/global' -import BLOG from '@/blog.config' import LazyImage from '@/components/LazyImage' import { siteConfig } from '@/lib/config' @@ -17,13 +16,14 @@ const Hero = props => { const [typed, changeType] = useState() const { siteInfo } = props const { locale } = useGlobal() + const GREETING_WORDS = siteConfig('GREETING_WORDS').split(',') useEffect(() => { updateHeaderHeight() if (!typed && window && document.getElementById('typed')) { changeType( new Typed('#typed', { - strings: BLOG.GREETING_WORDS.split(','), + strings: GREETING_WORDS, typeSpeed: 200, backSpeed: 100, backDelay: 400, From a47a7bce427b3d4498228d566ee3f89e0b5b230f Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Thu, 2 Nov 2023 09:41:29 +0800 Subject: [PATCH 07/48] 4.1.0 --- .env.local | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.local b/.env.local index 48b76dc9..0f9ee7c1 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=4.0.18 \ No newline at end of file +NEXT_PUBLIC_VERSION=4.1.0 \ No newline at end of file diff --git a/package.json b/package.json index 6164cbb4..ca67780c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "4.0.18", + "version": "4.1.0", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": { From 5ccf8823a64e2942a0b4a8d8f17545f1d5908c88 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Thu, 2 Nov 2023 14:10:46 +0800 Subject: [PATCH 08/48] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/DebugPanel.js | 8 ++-- components/ExternalPlugins.js | 42 +++++++++---------- components/ThemeSwitch.js | 8 ++-- lib/config.js | 20 ++++++++- lib/global.js | 10 ++--- lib/lang.js | 3 +- pages/404.js | 2 +- pages/[prefix]/index.js | 4 +- pages/archive/index.js | 2 +- pages/category/[category]/index.js | 2 +- pages/category/[category]/page/[page].js | 2 +- pages/category/index.js | 2 +- pages/index.js | 4 +- pages/page/[page].js | 2 +- pages/search/[keyword]/index.js | 2 +- pages/search/[keyword]/page/[page].js | 2 +- pages/search/index.js | 2 +- pages/tag/[tag]/index.js | 2 +- pages/tag/[tag]/page/[page].js | 2 +- pages/tag/index.js | 2 +- themes/example/components/BlogPostCard.js | 4 +- themes/example/components/Title.js | 2 +- themes/fukasawa/components/AsideLeft.js | 2 +- .../fukasawa/components/MenuItemCollapse.js | 4 +- themes/heo/components/MenuItemCollapse.js | 4 +- themes/matery/components/MenuItemCollapse.js | 4 +- themes/matery/components/MenuItemDrop.js | 4 +- themes/next/components/Logo.js | 2 +- themes/next/components/MenuItemCollapse.js | 4 +- .../nobelium/components/MenuItemCollapse.js | 4 +- themes/nobelium/components/MenuItemDrop.js | 6 +-- themes/simple/components/MenuItemCollapse.js | 4 +- themes/simple/components/MenuItemDrop.js | 4 +- themes/theme.js | 10 ++--- 34 files changed, 101 insertions(+), 80 deletions(-) diff --git a/components/DebugPanel.js b/components/DebugPanel.js index 026b5ee0..29408994 100644 --- a/components/DebugPanel.js +++ b/components/DebugPanel.js @@ -1,9 +1,10 @@ -import BLOG from '@/blog.config' import { useEffect, useState } from 'react' import Select from './Select' import { useGlobal } from '@/lib/global' import { THEMES } from '@/themes/theme' import { useRouter } from 'next/router' +import { siteConfigMap } from '@/lib/config' +import { getQueryParam } from '@/lib/utils' /** * @@ -13,13 +14,14 @@ const DebugPanel = () => { const [show, setShow] = useState(false) const { theme, switchTheme, locale } = useGlobal() const router = useRouter() + const currentTheme = getQueryParam(router.asPath, 'theme') || theme const [siteConfig, updateSiteConfig] = useState({}) // 主题下拉框 const themeOptions = THEMES?.map(t => ({ value: t, text: t })) useEffect(() => { - updateSiteConfig(Object.assign({}, BLOG)) + updateSiteConfig(Object.assign({}, siteConfigMap())) // updateThemeConfig(Object.assign({}, ThemeMap[BLOG.THEME].THEME_CONFIG)) }, []) @@ -71,7 +73,7 @@ const DebugPanel = () => {
    +
    - +
    {/* 切换主题加载时的全屏遮罩 */} diff --git a/lib/config.js b/lib/config.js index ff931386..56ae36ee 100644 --- a/lib/config.js +++ b/lib/config.js @@ -2,6 +2,7 @@ import BLOG from '@/blog.config' import { useGlobal } from './global' +import { deepClone } from './utils' /** * 读取配置 @@ -47,6 +48,23 @@ export const siteConfig = (key) => { if (!val) { val = BLOG[key] } - console.log('实际配置', key, val) + // console.log('实际配置', key, val) + return val +} + +/** + * 读取所有配置 + * 1. 优先读取NotionConfig表 + * 2. 其次读取环境变量 + * 3. 再读取blog.config.js文件 + * @param {*} key + * @returns + */ +export const siteConfigMap = () => { + const val = deepClone(BLOG) + for (const key in val) { + val[key] = siteConfig(key) + console.log('site', key, val[key], siteConfig(key)) + } return val } diff --git a/lib/global.js b/lib/global.js index 548b6d8c..204fc432 100644 --- a/lib/global.js +++ b/lib/global.js @@ -17,12 +17,11 @@ const GlobalContext = createContext() */ export function GlobalContextProvider(props) { const { children, siteInfo, categoryOptions, tagOptions, NOTION_CONFIG } = props - console.log('config', NOTION_CONFIG) const router = useRouter() - const [lang, updateLang] = useState(NOTION_CONFIG.LANG || BLOG.LANG) // 默认语言 - const [locale, updateLocale] = useState(generateLocaleDict(NOTION_CONFIG.LANG || BLOG.LANG)) // 默认语言 - const [theme, setTheme] = useState(NOTION_CONFIG.THEME || BLOG.THEME) // 默认博客主题 - const [isDarkMode, updateDarkMode] = useState(NOTION_CONFIG.APPEARANCE || BLOG.APPEARANCE === 'dark') // 默认深色模式 + const [lang, updateLang] = useState(NOTION_CONFIG?.LANG || BLOG.LANG) // 默认语言 + const [locale, updateLocale] = useState(generateLocaleDict(NOTION_CONFIG?.LANG || BLOG.LANG)) // 默认语言 + const [theme, setTheme] = useState(NOTION_CONFIG?.THEME || BLOG.THEME) // 默认博客主题 + const [isDarkMode, updateDarkMode] = useState(NOTION_CONFIG?.APPEARANCE || BLOG.APPEARANCE === 'dark') // 默认深色模式 const [onLoading, setOnLoading] = useState(false) // 抓取文章数据 // 切换主题 @@ -98,7 +97,6 @@ export function GlobalContextProvider(props) { /** * 切换主题时的特殊处理 - * @param {*} setTheme */ const checkThemeDOM = () => { if (isBrowser) { diff --git a/lib/lang.js b/lib/lang.js index d69da08f..15106572 100644 --- a/lib/lang.js +++ b/lib/lang.js @@ -34,7 +34,7 @@ export function generateLocaleDict(langString) { let userLocale // 将语言字符串拆分为语言和地区代码,例如将 "zh-CN" 拆分为 "zh" 和 "CN" - const [language, region] = langString.split(/[-_]/) + const [language, region] = langString?.split(/[-_]/) // 优先匹配语言和地区都匹配的情况 const specificLocale = `${language}-${region}` @@ -70,6 +70,7 @@ export function initLocale(lang, locale, changeLang, changeLocale) { if (queryLang !== lang) { currentLang = queryLang } + console.log('初始化语言', currentLang) changeLang(currentLang) saveLangToCookies(currentLang) diff --git a/pages/404.js b/pages/404.js index 1c9e5c30..ae8eea37 100644 --- a/pages/404.js +++ b/pages/404.js @@ -14,7 +14,7 @@ const NoFound = props => { props = { ...props, meta } // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) return } diff --git a/pages/[prefix]/index.js b/pages/[prefix]/index.js index b350fb18..dfc90fcc 100644 --- a/pages/[prefix]/index.js +++ b/pages/[prefix]/index.js @@ -67,7 +67,7 @@ const Slug = props => { }, [post]) const meta = { - title: post ? `${post?.title} | ${siteConfig('TITLE')}` : `${props?.siteConfig('TITLE') || BLOG.TITLE} | loading`, + title: post ? `${post?.title} | ${siteConfig('TITLE')}` : `${siteConfig('TITLE')} | loading`, description: post?.summary, type: post?.type, slug: post?.slug, @@ -77,7 +77,7 @@ const Slug = props => { } props = { ...props, lock, meta, setLock, validPassword } // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) return } diff --git a/pages/archive/index.js b/pages/archive/index.js index 3726291d..662cb7b6 100644 --- a/pages/archive/index.js +++ b/pages/archive/index.js @@ -13,7 +13,7 @@ const ArchiveIndex = props => { const { locale } = useGlobal() // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) useEffect(() => { if (isBrowser) { diff --git a/pages/category/[category]/index.js b/pages/category/[category]/index.js index a2c30722..9c90f22d 100644 --- a/pages/category/[category]/index.js +++ b/pages/category/[category]/index.js @@ -16,7 +16,7 @@ export default function Category(props) { const { locale } = useGlobal() // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${props.category} | ${locale.COMMON.CATEGORY} | ${ diff --git a/pages/category/[category]/page/[page].js b/pages/category/[category]/page/[page].js index 8a6cccc8..dee16235 100644 --- a/pages/category/[category]/page/[page].js +++ b/pages/category/[category]/page/[page].js @@ -16,7 +16,7 @@ export default function Category(props) { const { siteInfo } = props const { locale } = useGlobal() // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${props.category} | ${locale.COMMON.CATEGORY} | ${ diff --git a/pages/category/index.js b/pages/category/index.js index 8f6d98bc..78e7676e 100644 --- a/pages/category/index.js +++ b/pages/category/index.js @@ -16,7 +16,7 @@ export default function Category(props) { const { siteInfo } = props // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${locale.COMMON.CATEGORY} | ${siteConfig('TITLE')}`, diff --git a/pages/index.js b/pages/index.js index ac72c1b5..6a02cd98 100644 --- a/pages/index.js +++ b/pages/index.js @@ -3,9 +3,9 @@ import { getPostBlocks } from '@/lib/notion' import { getGlobalData } from '@/lib/notion/getNotionData' import { generateRss } from '@/lib/rss' import { generateRobotsTxt } from '@/lib/robots.txt' -import { useRouter } from 'next/router' import { getLayoutByTheme } from '@/themes/theme' import { siteConfig } from '@/lib/config' +import { useRouter } from 'next/router' /** * 首页布局 @@ -14,7 +14,7 @@ import { siteConfig } from '@/lib/config' */ const Index = props => { // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${siteConfig('TITLE')} | ${siteConfig('BIO')}`, diff --git a/pages/page/[page].js b/pages/page/[page].js index 131feb45..6e83c5a6 100644 --- a/pages/page/[page].js +++ b/pages/page/[page].js @@ -14,7 +14,7 @@ const Page = props => { const { siteInfo } = props // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${props?.page} | Page | ${siteConfig('TITLE')}`, diff --git a/pages/search/[keyword]/index.js b/pages/search/[keyword]/index.js index bc2514a1..cd6166ed 100644 --- a/pages/search/[keyword]/index.js +++ b/pages/search/[keyword]/index.js @@ -11,7 +11,7 @@ const Index = props => { const { locale } = useGlobal() // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteConfig('TITLE')}`, diff --git a/pages/search/[keyword]/page/[page].js b/pages/search/[keyword]/page/[page].js index c5c4aeb8..9de43cc1 100644 --- a/pages/search/[keyword]/page/[page].js +++ b/pages/search/[keyword]/page/[page].js @@ -11,7 +11,7 @@ const Index = props => { const { locale } = useGlobal() // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteConfig('TITLE')}`, diff --git a/pages/search/index.js b/pages/search/index.js index 31d09af3..1504fe86 100644 --- a/pages/search/index.js +++ b/pages/search/index.js @@ -15,7 +15,7 @@ const Search = props => { const { locale } = useGlobal() // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const router = useRouter() const keyword = getSearchKey(router) diff --git a/pages/tag/[tag]/index.js b/pages/tag/[tag]/index.js index f12cdc41..8805c686 100644 --- a/pages/tag/[tag]/index.js +++ b/pages/tag/[tag]/index.js @@ -15,7 +15,7 @@ const Tag = props => { const { tag, siteInfo } = props // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${tag} | ${locale.COMMON.TAGS} | ${siteConfig('TITLE')}`, diff --git a/pages/tag/[tag]/page/[page].js b/pages/tag/[tag]/page/[page].js index c708793b..7cbb2e6a 100644 --- a/pages/tag/[tag]/page/[page].js +++ b/pages/tag/[tag]/page/[page].js @@ -10,7 +10,7 @@ const Tag = props => { const { tag, siteInfo } = props // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${tag} | ${locale.COMMON.TAGS} | ${siteConfig('TITLE')}`, diff --git a/pages/tag/index.js b/pages/tag/index.js index cb6db4da..f82613eb 100644 --- a/pages/tag/index.js +++ b/pages/tag/index.js @@ -15,7 +15,7 @@ const TagIndex = props => { const { siteInfo } = props // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) + const Layout = getLayoutByTheme({ theme: siteConfig('THEME'), router: useRouter() }) const meta = { title: `${locale.COMMON.TAGS} | ${siteConfig('TITLE')}`, diff --git a/themes/example/components/BlogPostCard.js b/themes/example/components/BlogPostCard.js index fb91a307..5e9bdd33 100644 --- a/themes/example/components/BlogPostCard.js +++ b/themes/example/components/BlogPostCard.js @@ -41,9 +41,9 @@ const BlogPostCard = ({ post }) => {
    {/* 图片封面 */} {showPageCover && ( -
    +
    - +
    )} diff --git a/themes/example/components/Title.js b/themes/example/components/Title.js index a1512af2..5c251b0d 100644 --- a/themes/example/components/Title.js +++ b/themes/example/components/Title.js @@ -7,7 +7,7 @@ import { siteConfig } from '@/lib/config' */ export const Title = (props) => { const { post } = props - const title = post?.title || siteConfig('HOME_BANNER_IMAGE') + const title = post?.title || siteConfig('TITLE') const description = post?.description || siteConfig('AUTHOR') return
    diff --git a/themes/fukasawa/components/AsideLeft.js b/themes/fukasawa/components/AsideLeft.js index 131e5f31..f3ca1e98 100644 --- a/themes/fukasawa/components/AsideLeft.js +++ b/themes/fukasawa/components/AsideLeft.js @@ -63,7 +63,7 @@ function AsideLeft(props) {
    - {siteConfig('HOME_BANNER_IMAGE')} + {siteConfig('DESCRIPTION')}
    diff --git a/themes/fukasawa/components/MenuItemCollapse.js b/themes/fukasawa/components/MenuItemCollapse.js index a70e43bb..f854c16f 100644 --- a/themes/fukasawa/components/MenuItemCollapse.js +++ b/themes/fukasawa/components/MenuItemCollapse.js @@ -48,8 +48,8 @@ export const MenuItemCollapse = (props) => { {/* 折叠子菜单 */} {hasSubMenu && - {link.subMenus.map(sLink => { - return
    diff --git a/themes/heo/components/MenuItemCollapse.js b/themes/heo/components/MenuItemCollapse.js index 89b5f012..ab1472c1 100644 --- a/themes/heo/components/MenuItemCollapse.js +++ b/themes/heo/components/MenuItemCollapse.js @@ -42,8 +42,8 @@ export const MenuItemCollapse = ({ link }) => { {/* 折叠子菜单 */} {hasSubMenu && - {link.subMenus.map(sLink => { - return
    + {link.subMenus.map((sLink, index) => { + return
    {link?.icon && } {sLink.title} diff --git a/themes/matery/components/MenuItemCollapse.js b/themes/matery/components/MenuItemCollapse.js index 1bf88c81..dbd9aca1 100644 --- a/themes/matery/components/MenuItemCollapse.js +++ b/themes/matery/components/MenuItemCollapse.js @@ -49,8 +49,8 @@ export const MenuItemCollapse = ({ link }) => { {/* 折叠子菜单 */} {hasSubMenu && - {link.subMenus.map(sLink => { - return
    + {link.subMenus.map((sLink, index) => { + return
    {sLink.title} diff --git a/themes/matery/components/MenuItemDrop.js b/themes/matery/components/MenuItemDrop.js index 1fb3263a..5e666fa4 100644 --- a/themes/matery/components/MenuItemDrop.js +++ b/themes/matery/components/MenuItemDrop.js @@ -28,8 +28,8 @@ export const MenuItemDrop = ({ link }) => { {/* 子菜单 */} {hasSubMenu &&
      - {link.subMenus.map(sLink => { - return
    • + {link.subMenus.map((sLink, index) => { + return
    • {link?.icon &&   }{sLink.title} diff --git a/themes/next/components/Logo.js b/themes/next/components/Logo.js index 9619a454..7306052f 100644 --- a/themes/next/components/Logo.js +++ b/themes/next/components/Logo.js @@ -17,7 +17,7 @@ const Logo = props => { data-aos-delay="300" data-aos-once="true" data-aos-anchor-placement="top-bottom" - className='text-sm text-gray-300 font-light text-center'> {siteConfig('HOME_BANNER_IMAGE')}
    + className='text-sm text-gray-300 font-light text-center'> {siteConfig('DESCRIPTION')}
    ) diff --git a/themes/next/components/MenuItemCollapse.js b/themes/next/components/MenuItemCollapse.js index 20a26521..77fd4282 100644 --- a/themes/next/components/MenuItemCollapse.js +++ b/themes/next/components/MenuItemCollapse.js @@ -39,8 +39,8 @@ export const MenuItemCollapse = (props) => { {/* 折叠子菜单 */} {hasSubMenu && - {link.subMenus.map(sLink => { - return
    diff --git a/themes/nobelium/components/MenuItemCollapse.js b/themes/nobelium/components/MenuItemCollapse.js index d2fd9d87..8f53f622 100644 --- a/themes/nobelium/components/MenuItemCollapse.js +++ b/themes/nobelium/components/MenuItemCollapse.js @@ -43,8 +43,8 @@ export const MenuItemCollapse = (props) => { {/* 折叠子菜单 */} {hasSubMenu && - {link.subMenus.map(sLink => { - return
    + {link.subMenus.map((sLink, index) => { + return
    {sLink.title} diff --git a/themes/nobelium/components/MenuItemDrop.js b/themes/nobelium/components/MenuItemDrop.js index 9ea57461..0386910c 100644 --- a/themes/nobelium/components/MenuItemDrop.js +++ b/themes/nobelium/components/MenuItemDrop.js @@ -30,12 +30,12 @@ export const MenuItemDrop = ({ link }) => { {/* 子菜单 */} {hasSubMenu &&
      - {link.subMenus.map(sLink => { - return
    • + {link.subMenus.map((sLink, index) => { + return
      {link?.icon &&   }{sLink.title} -
    • +
    })} } diff --git a/themes/simple/components/MenuItemCollapse.js b/themes/simple/components/MenuItemCollapse.js index 1d3face5..d335d806 100644 --- a/themes/simple/components/MenuItemCollapse.js +++ b/themes/simple/components/MenuItemCollapse.js @@ -43,8 +43,8 @@ export const MenuItemCollapse = (props) => { {/* 折叠子菜单 */} {hasSubMenu && - {link.subMenus.map(sLink => { - return
    + {link.subMenus.map((sLink, index) => { + return
    {sLink?.icon && }{sLink.title} diff --git a/themes/simple/components/MenuItemDrop.js b/themes/simple/components/MenuItemDrop.js index 9f79e609..81f57d31 100644 --- a/themes/simple/components/MenuItemDrop.js +++ b/themes/simple/components/MenuItemDrop.js @@ -28,8 +28,8 @@ export const MenuItemDrop = ({ link }) => { {/* 子菜单 */} {hasSubMenu &&
      - {link.subMenus.map(sLink => { - return
    • + {link.subMenus.map((sLink, index) => { + return
    • {sLink?.icon &&   }{sLink.title} diff --git a/themes/theme.js b/themes/theme.js index f03f3fe6..d375d661 100644 --- a/themes/theme.js +++ b/themes/theme.js @@ -12,13 +12,13 @@ export const { THEMES = [] } = getConfig().publicRuntimeConfig * @param {*} router * @returns */ -export const getLayoutByTheme = (router) => { - const themeQuery = getQueryParam(router.asPath, 'theme') || BLOG.THEME - const layout = getLayoutNameByPath(router.pathname) +export const getLayoutByTheme = ({ router, theme }) => { + const themeQuery = getQueryParam(router.asPath, 'theme') || theme + const layoutName = getLayoutNameByPath(router.pathname) if (themeQuery !== BLOG.THEME) { - return dynamic(() => import(`@/themes/${themeQuery}`).then(m => m[layout]), { ssr: true }) + return dynamic(() => import(`@/themes/${themeQuery}`).then(m => m[layoutName]), { ssr: true }) } else { - return ThemeComponents[layout] + return ThemeComponents[layoutName] } } From 0f1f4157826fa76403511334e3e19fb657c5a42c Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Thu, 2 Nov 2023 17:01:00 +0800 Subject: [PATCH 09/48] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/CusdisComponent.js | 4 +-- components/DarkModeButton.js | 17 ++------- components/ThemeSwitch.js | 53 +++++++++++++++++++++------- lib/cache/cache_manager.js | 31 ++++++++++------- lib/cache/local_file_cache.js | 10 +++++- lib/config.js | 2 +- lib/global.js | 56 +++++++++++++++++++----------- lib/lang.js | 18 +++++----- lib/lang/en-US.js | 2 +- lib/lang/fr-FR.js | 2 +- lib/lang/ja-JP.js | 2 +- lib/lang/tr-TR.js | 2 +- lib/lang/zh-CN.js | 2 +- lib/lang/zh-HK.js | 1 + lib/lang/zh-TW.js | 2 +- pages/api/cache.js | 15 ++++++++ themes/next/components/MenuList.js | 4 +-- 17 files changed, 141 insertions(+), 82 deletions(-) create mode 100644 pages/api/cache.js diff --git a/components/CusdisComponent.js b/components/CusdisComponent.js index ad780aea..a276eac6 100644 --- a/components/CusdisComponent.js +++ b/components/CusdisComponent.js @@ -5,7 +5,7 @@ import { useEffect } from 'react' import { loadExternalResource } from '@/lib/utils' const CusdisComponent = ({ frontMatter }) => { - const { locale } = useGlobal() + const { lang } = useGlobal() const router = useRouter() const { isDarkMode } = useGlobal() @@ -18,7 +18,7 @@ const CusdisComponent = ({ frontMatter }) => { }, [isDarkMode]) return
      { const { cRef, className } = props - const { isDarkMode, updateDarkMode } = useGlobal() + const { isDarkMode, toggleDarkMode } = useGlobal() /** * 对外暴露方法 @@ -16,22 +15,12 @@ const DarkModeButton = (props) => { useImperativeHandle(cRef, () => { return { handleChangeDarkMode: () => { - handleChangeDarkMode() + toggleDarkMode() } } }) - // 用户手动设置主题 - const handleChangeDarkMode = () => { - const newStatus = !isDarkMode - saveDarkModeToCookies(newStatus) - updateDarkMode(newStatus) - const htmlElement = document.getElementsByTagName('html')[0] - htmlElement.classList?.remove(newStatus ? 'light' : 'dark') - htmlElement.classList?.add(newStatus ? 'dark' : 'light') - } - - return
      + return
      {isDarkMode ? : }
      } diff --git a/components/ThemeSwitch.js b/components/ThemeSwitch.js index a4b13f31..0c74a63e 100644 --- a/components/ThemeSwitch.js +++ b/components/ThemeSwitch.js @@ -5,19 +5,21 @@ import { THEMES } from '@/themes/theme' import { useRouter } from 'next/router' import DarkModeButton from './DarkModeButton' import { getQueryParam } from '@/lib/utils' +import LANGS from '@/lib/lang' /** * * @returns 主题切换 */ const ThemeSwitch = () => { - const { theme } = useGlobal() + const { theme, lang, changeLang, locale, isDarkMode, toggleDarkMode } = useGlobal() const router = useRouter() const currentTheme = getQueryParam(router.asPath, 'theme') || theme + // const currentLang = getQueryParam(router.asPath, 'lang') || lang const [isLoading, setIsLoading] = useState(false) // 修改当前路径url中的 theme 参数 // 例如 http://localhost?theme=hexo 跳转到 http://localhost?theme=newTheme - const onSelectChange = (e) => { + const onThemeSelectChange = (e) => { setIsLoading(true) const newTheme = e.target.value const query = router.query @@ -27,27 +29,52 @@ const ThemeSwitch = () => { }) } + const onLangSelectChange = (e) => { + const newLang = e.target.value + changeLang(newLang) + } + return (<> -
      -
      - -
      - + {Object.keys(LANGS)?.map(t => { + return + })} + +
      +
      + + {/* 主题切换按钮 */} +
      + +
      +
      -
      - {/* 切换主题加载时的全屏遮罩 */} -
      - -
      + + {/* 切换主题加载时的全屏遮罩 */} +
      + +
      ) } diff --git a/lib/cache/cache_manager.js b/lib/cache/cache_manager.js index 8796d3f4..4928bca9 100644 --- a/lib/cache/cache_manager.js +++ b/lib/cache/cache_manager.js @@ -3,15 +3,6 @@ import FileCache from './local_file_cache' import MongoCache from './mongo_db_cache' import BLOG from '@/blog.config' -let api -if (process.env.MONGO_DB_URL && process.env.MONGO_DB_NAME) { - api = MongoCache -} else if (process.env.ENABLE_FILE_CACHE) { - api = FileCache -} else { - api = MemoryCache -} - /** * 为减少频繁接口请求,notion数据将被缓存 * @param {*} key @@ -19,11 +10,11 @@ if (process.env.MONGO_DB_URL && process.env.MONGO_DB_NAME) { */ export async function getDataFromCache(key, force) { if (BLOG.ENABLE_CACHE || force) { - const dataFromCache = await api.getCache(key) + const dataFromCache = await getApi().getCache(key) if (JSON.stringify(dataFromCache) === '[]') { return null } - return api.getCache(key) + return getApi().getCache(key) } else { return null } @@ -33,12 +24,26 @@ export async function setDataToCache(key, data) { if (!data) { return } - await api.setCache(key, data) + await getApi().setCache(key, data) } export async function delCacheData(key) { if (!BLOG.ENABLE_CACHE) { return } - await api.delCache(key) + await getApi().delCache(key) +} + +/** + * 缓存实现类 + * @returns + */ +function getApi() { + if (process.env.MONGO_DB_URL && process.env.MONGO_DB_NAME) { + return MongoCache + } else if (process.env.ENABLE_FILE_CACHE) { + return FileCache + } else { + return MemoryCache + } } diff --git a/lib/cache/local_file_cache.js b/lib/cache/local_file_cache.js index cda7f35a..c411d6e5 100644 --- a/lib/cache/local_file_cache.js +++ b/lib/cache/local_file_cache.js @@ -41,7 +41,7 @@ export async function setCache (key, data) { fs.writeFileSync(jsonFile, JSON.stringify(json)) } -export async function delCache (key, data) { +export async function delCache (key) { const exist = await fs.existsSync(jsonFile) const json = exist ? JSON.parse(await fs.readFileSync(jsonFile)) : {} delete json.key @@ -49,4 +49,12 @@ export async function delCache (key, data) { fs.writeFileSync(jsonFile, JSON.stringify(json)) } +/** + * 清理缓存 + */ +export async function cleanCache() { + const json = {} + fs.writeFileSync(jsonFile, JSON.stringify(json)) +} + export default { getCache, setCache, delCache } diff --git a/lib/config.js b/lib/config.js index 56ae36ee..36a1112d 100644 --- a/lib/config.js +++ b/lib/config.js @@ -64,7 +64,7 @@ export const siteConfigMap = () => { const val = deepClone(BLOG) for (const key in val) { val[key] = siteConfig(key) - console.log('site', key, val[key], siteConfig(key)) + // console.log('site', key, val[key], siteConfig(key)) } return val } diff --git a/lib/global.js b/lib/global.js index 204fc432..eaabd278 100644 --- a/lib/global.js +++ b/lib/global.js @@ -1,11 +1,10 @@ import { generateLocaleDict, initLocale } from './lang' import { createContext, useContext, useEffect, useState } from 'react' import { useRouter } from 'next/router' -import { THEMES, initDarkMode } from '@/themes/theme' +import { THEMES, initDarkMode, saveDarkModeToCookies } from '@/themes/theme' import BLOG from '@/blog.config' import NProgress from 'nprogress' -import { isBrowser } from './utils' const GlobalContext = createContext() @@ -35,17 +34,34 @@ export function GlobalContextProvider(props) { return newTheme } + // 切换深色模式 + const toggleDarkMode = () => { + const newStatus = !isDarkMode + saveDarkModeToCookies(newStatus) + updateDarkMode(newStatus) + const htmlElement = document.getElementsByTagName('html')[0] + htmlElement.classList?.remove(newStatus ? 'light' : 'dark') + htmlElement.classList?.add(newStatus ? 'dark' : 'light') + } + + /** + * 更新语言 + */ + function changeLang(lang) { + if (lang) { + updateLang(lang) + updateLocale(generateLocaleDict(lang)) + } + } + useEffect(() => { - initLocale(lang, locale, updateLang, updateLocale) initDarkMode(updateDarkMode) - checkThemeDOM() + initLocale(lang, locale, updateLang, updateLocale) }, []) - // 加载默认主题 - // useEffect(() => { - // const queryTheme = getQueryVariable('theme') || theme - // setTheme(queryTheme) - // }, [router]) + useEffect(() => { + checkThemeDOM() + }) // 加载进度条 useEffect(() => { @@ -62,6 +78,7 @@ export function GlobalContextProvider(props) { NProgress.done() setOnLoading(false) } + router.events.on('routeChangeStart', handleStart) router.events.on('routeChangeError', handleStop) router.events.on('routeChangeComplete', handleStop) @@ -75,10 +92,11 @@ export function GlobalContextProvider(props) { return ( { - if (isBrowser) { - setTimeout(() => { - const elements = document.querySelectorAll('[id^="theme-"]') - if (elements?.length > 1) { - elements[elements.length - 1].scrollIntoView() - // 删除前面的元素,只保留最后一个元素 - for (let i = 0; i < elements.length - 1; i++) { - elements[i].parentNode.removeChild(elements[i]) - } - } - }, 500) + const elements = document.querySelectorAll('[id^="theme-"]') + if (elements?.length > 1) { + elements[elements.length - 1].scrollIntoView() + // 删除前面的元素,只保留最后一个元素 + for (let i = 0; i < elements.length - 1; i++) { + elements[i].parentNode.removeChild(elements[i]) + } } } diff --git a/lib/lang.js b/lib/lang.js index 15106572..3e2307f7 100644 --- a/lib/lang.js +++ b/lib/lang.js @@ -12,7 +12,7 @@ import { getQueryVariable, isBrowser, mergeDeep } from './utils' * 在这里配置所有支持的语言 * 国家-地区 */ -const lang = { +const LANGS = { 'en-US': enUS, 'zh-CN': zhCN, 'zh-HK': zhHK, @@ -22,7 +22,7 @@ const lang = { 'ja-JP': jaJP } -export default lang +export default LANGS /** * 获取当前语言字典 @@ -30,7 +30,7 @@ export default lang * @returns 不同语言对应字典 */ export function generateLocaleDict(langString) { - const supportedLocales = Object.keys(lang) + const supportedLocales = Object.keys(LANGS) let userLocale // 将语言字符串拆分为语言和地区代码,例如将 "zh-CN" 拆分为 "zh" 和 "CN" @@ -39,24 +39,24 @@ export function generateLocaleDict(langString) { // 优先匹配语言和地区都匹配的情况 const specificLocale = `${language}-${region}` if (supportedLocales.includes(specificLocale)) { - userLocale = lang[specificLocale] + userLocale = LANGS[specificLocale] } // 然后尝试匹配只有语言匹配的情况 if (!userLocale) { const languageOnlyLocales = supportedLocales.filter(locale => locale.startsWith(language)) if (languageOnlyLocales.length > 0) { - userLocale = lang[languageOnlyLocales[0]] + userLocale = LANGS[languageOnlyLocales[0]] } } // 如果还没匹配到,则返回最接近的语言包 if (!userLocale) { const fallbackLocale = supportedLocales.find(locale => locale.startsWith('en')) - userLocale = lang[fallbackLocale] + userLocale = LANGS[fallbackLocale] } - return mergeDeep({}, lang['en-US'], userLocale) + return mergeDeep({}, LANGS['en-US'], userLocale) } /** @@ -67,10 +67,10 @@ export function initLocale(lang, locale, changeLang, changeLocale) { if (isBrowser) { const queryLang = getQueryVariable('lang') || loadLangFromCookies() let currentLang = lang - if (queryLang !== lang) { + if (queryLang && queryLang !== 'undefined' && queryLang !== lang) { currentLang = queryLang } - console.log('初始化语言', currentLang) + changeLang(currentLang) saveLangToCookies(currentLang) diff --git a/lib/lang/en-US.js b/lib/lang/en-US.js index 51e38115..594ddfc0 100644 --- a/lib/lang/en-US.js +++ b/lib/lang/en-US.js @@ -1,5 +1,5 @@ export default { - LOCALE: 'en-US', + LOCALE: 'English', MENU: { WALK_AROUND: 'Walk Around', CATEGORY: 'Category', diff --git a/lib/lang/fr-FR.js b/lib/lang/fr-FR.js index 30089a70..2bc40057 100644 --- a/lib/lang/fr-FR.js +++ b/lib/lang/fr-FR.js @@ -1,5 +1,5 @@ export default { - LOCALE: 'fr-FR', + LOCALE: 'français', NAV: { INDEX: 'Accueil', RSS: 'RSS', diff --git a/lib/lang/ja-JP.js b/lib/lang/ja-JP.js index ab0e81f8..c27eef0b 100644 --- a/lib/lang/ja-JP.js +++ b/lib/lang/ja-JP.js @@ -1,5 +1,5 @@ export default { - LOCALE: 'ja-JP', + LOCALE: '日本語', NAV: { INDEX: 'ホーム', RSS: '購読', diff --git a/lib/lang/tr-TR.js b/lib/lang/tr-TR.js index 227b3fba..5be7a520 100644 --- a/lib/lang/tr-TR.js +++ b/lib/lang/tr-TR.js @@ -1,5 +1,5 @@ export default { - LOCALE: 'tr-TR', + LOCALE: 'Türkçe', NAV: { INDEX: 'Blog', RSS: 'RSS', diff --git a/lib/lang/zh-CN.js b/lib/lang/zh-CN.js index 91a4600a..e29af3d5 100644 --- a/lib/lang/zh-CN.js +++ b/lib/lang/zh-CN.js @@ -1,5 +1,5 @@ export default { - LOCALE: 'zh-CN', + LOCALE: '中文(简体)', MENU: { WALK_AROUND: '随便逛逛', CATEGORY: '博客分类', diff --git a/lib/lang/zh-HK.js b/lib/lang/zh-HK.js index 6a05df55..f434fe6e 100644 --- a/lib/lang/zh-HK.js +++ b/lib/lang/zh-HK.js @@ -1,4 +1,5 @@ export default { + LOCALE: '中文(繁体香港)', NAV: { INDEX: '網誌', RSS: '訂閱', diff --git a/lib/lang/zh-TW.js b/lib/lang/zh-TW.js index 673fe109..de746c08 100644 --- a/lib/lang/zh-TW.js +++ b/lib/lang/zh-TW.js @@ -1,5 +1,5 @@ export default { - LOCALE: 'zh-TW', + LOCALE: '中文(繁体台湾)', NAV: { INDEX: '部落格', RSS: '訂閱', diff --git a/pages/api/cache.js b/pages/api/cache.js new file mode 100644 index 00000000..97738651 --- /dev/null +++ b/pages/api/cache.js @@ -0,0 +1,15 @@ +import { cleanCache } from '@/lib/cache/local_file_cache' + +/** + * 清理缓存 + * @param {*} req + * @param {*} res + */ +export default async function handler(req, res) { + try { + await cleanCache() + res.status(200).json({ status: 'success', message: 'Clean cache successful!' }) + } catch (error) { + res.status(400).json({ status: 'error', message: 'Clean cache failed!', error }) + } +} diff --git a/themes/next/components/MenuList.js b/themes/next/components/MenuList.js index ec03a7bd..c9131929 100644 --- a/themes/next/components/MenuList.js +++ b/themes/next/components/MenuList.js @@ -40,12 +40,12 @@ export const MenuList = (props) => { data-aos-once="true" data-aos-anchor-placement="top-bottom" className='hidden md:block leading-8 text-gray-500 dark:text-gray-400 font-sans'> - {links.map(link => link && link.show && )} + {links.map((link, index) => link && link.show && )} {/* 移动端菜单 */} ) From ce68786c00e0f2a3070da33411600648ab59efbd Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Thu, 2 Nov 2023 17:06:41 +0800 Subject: [PATCH 10/48] log --- components/ThemeSwitch.js | 2 +- lib/notion/getNotionConfig.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/ThemeSwitch.js b/components/ThemeSwitch.js index 0c74a63e..d3913d30 100644 --- a/components/ThemeSwitch.js +++ b/components/ThemeSwitch.js @@ -45,7 +45,7 @@ const ThemeSwitch = () => { {/* 翻译按钮 */}
      - +
      { + if (e.key === 'Enter') { + submitPassword() + } + }} + ref={passwordInputRef} // 绑定ref到passwordInputRef变量 + className='outline-none w-full text-sm pl-5 rounded-l transition focus:shadow-lg font-light leading-10 bg-gray-100 dark:bg-gray-500'> + +
      +  {locale.COMMON.SUBMIT} +
      +
      +
      +
      +
      +
      +} diff --git a/themes/commerce/components/ArticleRecommend.js b/themes/commerce/components/ArticleRecommend.js new file mode 100644 index 00000000..dc5ef58e --- /dev/null +++ b/themes/commerce/components/ArticleRecommend.js @@ -0,0 +1,60 @@ +import Link from 'next/link' +import CONFIG from '../config' +import BLOG from '@/blog.config' +import { useGlobal } from '@/lib/global' +import LazyImage from '@/components/LazyImage' + +/** + * 关联推荐文章 + * @param {prev,next} param0 + * @returns + */ +export default function ArticleRecommend({ recommendPosts, siteInfo }) { + const { locale } = useGlobal() + + if ( + !CONFIG.ARTICLE_RECOMMEND || + !recommendPosts || + recommendPosts.length === 0 + ) { + return <> + } + + return ( +
      +
      +
      + + {locale.COMMON.RELATE_POSTS} +
      +
      +
      + {recommendPosts.map(post => { + const headerImage = post?.pageCoverThumbnail + ? post.pageCoverThumbnail + : siteInfo?.pageCover + + return ( + ( + +
      +
      +
      + {post.title} +
      +
      + +
      + + ) + ) + })} +
      +
      + ) +} diff --git a/themes/commerce/components/BlogPostArchive.js b/themes/commerce/components/BlogPostArchive.js new file mode 100644 index 00000000..85fe02d1 --- /dev/null +++ b/themes/commerce/components/BlogPostArchive.js @@ -0,0 +1,49 @@ +import React from 'react' +import Link from 'next/link' +import BLOG from '@/blog.config' +/** + * 博客归档列表 + * @param posts 所有文章 + * @param archiveTitle 归档标题 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostArchive = ({ posts = [], archiveTitle }) => { + if (!posts || posts.length === 0) { + return <> + } else { + return ( +
      +
      + {archiveTitle} +
      +
        + {posts?.map(post => ( +
      • +
        + {post.date?.start_date}{' '} +   + + + {post.title} + + +
        +
      • + ))} +
      +
      + ) + } +} + +export default BlogPostArchive diff --git a/themes/commerce/components/BlogPostCard.js b/themes/commerce/components/BlogPostCard.js new file mode 100644 index 00000000..f1febbdd --- /dev/null +++ b/themes/commerce/components/BlogPostCard.js @@ -0,0 +1,49 @@ +import Link from 'next/link' +import React from 'react' +import CONFIG from '../config' +import { BlogPostCardInfo } from './BlogPostCardInfo' +import BLOG from '@/blog.config' +import LazyImage from '@/components/LazyImage' +// import Image from 'next/image' + +const BlogPostCard = ({ index, post, showSummary, siteInfo }) => { + const showPreview = CONFIG.POST_LIST_PREVIEW && post.blockMap + if (post && !post.pageCoverThumbnail && CONFIG.POST_LIST_COVER_DEFAULT) { + post.pageCoverThumbnail = siteInfo?.pageCover + } + const showPageCover = CONFIG.POST_LIST_COVER && post?.pageCoverThumbnail && !showPreview + // const delay = (index % 2) * 200 + + return ( + +
      +
      + + {/* 文字内容 */} + + + {/* 图片封面 */} + {showPageCover && ( +
      + + + +
      + )} + +
      + +
      + + ) +} + +export default BlogPostCard diff --git a/themes/commerce/components/BlogPostCardInfo.js b/themes/commerce/components/BlogPostCardInfo.js new file mode 100644 index 00000000..eb2b5676 --- /dev/null +++ b/themes/commerce/components/BlogPostCardInfo.js @@ -0,0 +1,94 @@ +import NotionPage from '@/components/NotionPage' +import Link from 'next/link' +import TagItemMini from './TagItemMini' +import TwikooCommentCount from '@/components/TwikooCommentCount' +import BLOG from '@/blog.config' +import { formatDateFmt } from '@/lib/formatDate' + +/** + * 博客列表的文字内容 + * @param {*} param0 + * @returns + */ +export const BlogPostCardInfo = ({ post, showPreview, showPageCover, showSummary }) => { + return
      +
      + {/* 标题 */} + + + {post.title} + + + + {/* 分类 */} + { post?.category &&
      + + + + {post.category} + + + + +
      } + + {/* 摘要 */} + {(!showPreview || showSummary) && !post.results && ( +

      + {post.summary} +

      + )} + + {/* 搜索结果 */} + {post.results && ( +

      + {post.results.map((r, index) => ( + {r} + ))} +

      + )} + {/* 预览 */} + {showPreview && ( +
      + +
      + )} + +
      + +
      + {/* 日期标签 */} +
      + {/* 日期 */} + + + + {post?.publishDay || post.lastEditedDay} + + + +
      +
      + {' '} + {post.tagItems?.map(tag => ( + + ))} +
      +
      +
      +
      +
      +} diff --git a/themes/commerce/components/BlogPostListEmpty.js b/themes/commerce/components/BlogPostListEmpty.js new file mode 100644 index 00000000..5f75c3e7 --- /dev/null +++ b/themes/commerce/components/BlogPostListEmpty.js @@ -0,0 +1,14 @@ +import { useGlobal } from '@/lib/global' + +/** + * 空白博客 列表 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListEmpty = ({ currentSearch }) => { + const { locale } = useGlobal() + return
      +
      {locale.COMMON.NO_MORE} {(currentSearch &&
      {currentSearch}
      )}
      +
      +} +export default BlogPostListEmpty diff --git a/themes/commerce/components/BlogPostListPage.js b/themes/commerce/components/BlogPostListPage.js new file mode 100644 index 00000000..92008f83 --- /dev/null +++ b/themes/commerce/components/BlogPostListPage.js @@ -0,0 +1,34 @@ +import BlogPostCard from './BlogPostCard' +import PaginationNumber from './PaginationNumber' +import BLOG from '@/blog.config' +import BlogPostListEmpty from './BlogPostListEmpty' + +/** + * 文章列表分页表格 + * @param page 当前页 + * @param posts 所有文章 + * @param tags 所有标签 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListPage = ({ page = 1, posts = [], postCount, siteInfo }) => { + const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) + const showPagination = postCount >= BLOG.POSTS_PER_PAGE + if (!posts || posts.length === 0 || page > totalPage) { + return + } else { + return ( +
      + {/* 文章列表 */} +
      + {posts?.map(post => ( + + ))} +
      + {showPagination && } +
      + ) + } +} + +export default BlogPostListPage diff --git a/themes/commerce/components/BlogPostListScroll.js b/themes/commerce/components/BlogPostListScroll.js new file mode 100644 index 00000000..7646b056 --- /dev/null +++ b/themes/commerce/components/BlogPostListScroll.js @@ -0,0 +1,75 @@ +import BLOG from '@/blog.config' +import BlogPostCard from './BlogPostCard' +import BlogPostListEmpty from './BlogPostListEmpty' +import { useGlobal } from '@/lib/global' +import React from 'react' +import CONFIG from '../config' +import { getListByPage } from '@/lib/utils' + +/** + * 博客列表滚动分页 + * @param posts 所有文章 + * @param tags 所有标签 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG.POST_LIST_SUMMARY, siteInfo }) => { + const postsPerPage = BLOG.POSTS_PER_PAGE + const [page, updatePage] = React.useState(1) + const postsToShow = getListByPage(posts, page, postsPerPage) + + let hasMore = false + if (posts) { + const totalCount = posts.length + hasMore = page * postsPerPage < totalCount + } + + const handleGetMore = () => { + if (!hasMore) return + updatePage(page + 1) + } + + // 监听滚动自动分页加载 + const scrollTrigger = () => { + requestAnimationFrame(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }) + } + + // 监听滚动 + React.useEffect(() => { + window.addEventListener('scroll', scrollTrigger) + return () => { + window.removeEventListener('scroll', scrollTrigger) + } + }) + + const targetRef = React.useRef(null) + const { locale } = useGlobal() + + if (!postsToShow || postsToShow.length === 0) { + return + } else { + return
      + + {/* 文章列表 */} +
      + {postsToShow.map(post => ( + + ))} +
      + +
      +
      { handleGetMore() }} + className='w-full my-4 py-4 text-center cursor-pointer rounded-xl dark:text-gray-200' + > {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE}`}
      +
      +
      + } +} + +export default BlogPostListScroll diff --git a/themes/commerce/components/Card.js b/themes/commerce/components/Card.js new file mode 100644 index 00000000..c2db0e49 --- /dev/null +++ b/themes/commerce/components/Card.js @@ -0,0 +1,9 @@ +const Card = ({ children, headerSlot, className }) => { + return
      + <>{headerSlot} +
      + {children} +
      +
      +} +export default Card diff --git a/themes/commerce/components/Catalog.js b/themes/commerce/components/Catalog.js new file mode 100644 index 00000000..5cf1e4ad --- /dev/null +++ b/themes/commerce/components/Catalog.js @@ -0,0 +1,95 @@ +import { useCallback, useEffect, useRef, useState } from 'react' +import throttle from 'lodash.throttle' +import { uuidToId } from 'notion-utils' +import Progress from './Progress' +import { useGlobal } from '@/lib/global' + +/** + * 目录导航组件 + * @param toc + * @returns {JSX.Element} + * @constructor + */ +const Catalog = ({ toc }) => { + const { locale } = useGlobal() + // 监听滚动事件 + useEffect(() => { + window.addEventListener('scroll', actionSectionScrollSpy) + actionSectionScrollSpy() + return () => { + window.removeEventListener('scroll', actionSectionScrollSpy) + } + }, []) + + // 目录自动滚动 + const tRef = useRef(null) + const tocIds = [] + + // 同步选中目录事件 + const [activeSection, setActiveSection] = useState(null) + + const throttleMs = 200 + const actionSectionScrollSpy = useCallback(throttle(() => { + const sections = document.getElementsByClassName('notion-h') + let prevBBox = null + let currentSectionId = activeSection + for (let i = 0; i < sections.length; ++i) { + const section = sections[i] + if (!section || !(section instanceof Element)) continue + if (!currentSectionId) { + currentSectionId = section.getAttribute('data-id') + } + const bbox = section.getBoundingClientRect() + const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0 + const offset = Math.max(150, prevHeight / 4) + // GetBoundingClientRect returns values relative to viewport + if (bbox.top - offset < 0) { + currentSectionId = section.getAttribute('data-id') + prevBBox = bbox + continue + } + // No need to continue loop, if last element has been detected + break + } + setActiveSection(currentSectionId) + const index = tocIds.indexOf(currentSectionId) || 0 + tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' }) + }, throttleMs)) + + // 无目录就直接返回空 + if (!toc || toc.length < 1) { + return <> + } + + return
      +
      {locale.COMMON.TABLE_OF_CONTENTS}
      +
      + +
      +
      + + +
      +
      +} + +export default Catalog diff --git a/themes/commerce/components/CategoryGroup.js b/themes/commerce/components/CategoryGroup.js new file mode 100644 index 00000000..3e8ff7d0 --- /dev/null +++ b/themes/commerce/components/CategoryGroup.js @@ -0,0 +1,31 @@ +import Link from 'next/link' +import React from 'react' + +const CategoryGroup = ({ currentCategory, categories }) => { + if (!categories) { + return <> + } + return <> +
      + {categories.map(category => { + const selected = currentCategory === category.name + return ( + + +
      {category.name}({category.count})
      + + + ); + })} +
      + ; +} + +export default CategoryGroup diff --git a/themes/commerce/components/FloatDarkModeButton.js b/themes/commerce/components/FloatDarkModeButton.js new file mode 100644 index 00000000..f693d1f0 --- /dev/null +++ b/themes/commerce/components/FloatDarkModeButton.js @@ -0,0 +1,31 @@ +import { useGlobal } from '@/lib/global' +import { saveDarkModeToCookies } from '@/themes/theme' +import CONFIG from '../config' + +export default function FloatDarkModeButton () { + const { isDarkMode, updateDarkMode } = useGlobal() + + if (!CONFIG.WIDGET_DARK_MODE) { + return <> + } + + // 用户手动设置主题 + const handleChangeDarkMode = () => { + const newStatus = !isDarkMode + saveDarkModeToCookies(newStatus) + updateDarkMode(newStatus) + const htmlElement = document.getElementsByTagName('html')[0] + htmlElement.classList?.remove(newStatus ? 'light' : 'dark') + htmlElement.classList?.add(newStatus ? 'dark' : 'light') + } + + return ( +
      + +
      + ) +} diff --git a/themes/commerce/components/Footer.js b/themes/commerce/components/Footer.js new file mode 100644 index 00000000..ced637e9 --- /dev/null +++ b/themes/commerce/components/Footer.js @@ -0,0 +1,36 @@ +import React from 'react' +import BLOG from '@/blog.config' +import { siteConfig } from '@/lib/config' + +const Footer = ({ title }) => { + const d = new Date() + const currentYear = d.getFullYear() + const copyrightDate = (function() { + if (Number.isInteger(BLOG.SINCE) && BLOG.SINCE < currentYear) { + return BLOG.SINCE + '-' + currentYear + } + return currentYear + })() + + return ( + + ) +} + +export default Footer diff --git a/themes/commerce/components/Hero.js b/themes/commerce/components/Hero.js new file mode 100644 index 00000000..ef50465f --- /dev/null +++ b/themes/commerce/components/Hero.js @@ -0,0 +1,68 @@ +// import Image from 'next/image' +import { useEffect, useState } from 'react' +import Typed from 'typed.js' +import CONFIG from '../config' +import NavButtonGroup from './NavButtonGroup' +import { useGlobal } from '@/lib/global' +import LazyImage from '@/components/LazyImage' +import { siteConfig } from '@/lib/config' + +let wrapperTop = 0 + +/** + * 顶部全屏大图 + * @returns + */ +const Hero = props => { + const [typed, changeType] = useState() + const { siteInfo } = props + const { locale } = useGlobal() + const scrollToWrapper = () => { + window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) + } + const GREETING_WORDS = siteConfig('GREETING_WORDS').split(',') + useEffect(() => { + updateHeaderHeight() + + if (!typed && window && document.getElementById('typed')) { + changeType( + new Typed('#typed', { + strings: GREETING_WORDS, + typeSpeed: 200, + backSpeed: 100, + backDelay: 400, + showCursor: true, + smartBackspace: true + }) + ) + } + + window.addEventListener('resize', updateHeaderHeight) + return () => { + window.removeEventListener('resize', updateHeaderHeight) + } + }) + + function updateHeaderHeight() { + requestAnimationFrame(() => { + const wrapperElement = document.getElementById('wrapper') + wrapperTop = wrapperElement?.offsetTop + }) + } + + return ( + + ) +} + +export default Hero diff --git a/themes/commerce/components/HexoRecentComments.js b/themes/commerce/components/HexoRecentComments.js new file mode 100644 index 00000000..2ebf00c8 --- /dev/null +++ b/themes/commerce/components/HexoRecentComments.js @@ -0,0 +1,47 @@ +import React from 'react' +import BLOG from '@/blog.config' +import Card from '@/themes/hexo/components/Card' +import { useGlobal } from '@/lib/global' +import Link from 'next/link' +import { RecentComments } from '@waline/client' + +/** + * @see https://waline.js.org/guide/get-started.html + * @param {*} props + * @returns + */ +const HexoRecentComments = (props) => { + const [comments, updateComments] = React.useState([]) + const { locale } = useGlobal() + const [onLoading, changeLoading] = React.useState(true) + React.useEffect(() => { + RecentComments({ + serverURL: BLOG.COMMENT_WALINE_SERVER_URL, + count: 5 + }).then(({ comments }) => { + changeLoading(false) + updateComments(comments) + }) + }, []) + + return ( + +
      + + {locale.COMMON.RECENT_COMMENTS} +
      + + {onLoading &&
      Loading...
      } + {!onLoading && comments && comments.length === 0 &&
      No Comments
      } + {!onLoading && comments && comments.length > 0 && comments.map((comment) =>
      +
      +
      + --{comment.nick} +
      +
      )} + + + ) +} + +export default HexoRecentComments diff --git a/themes/commerce/components/InfoCard.js b/themes/commerce/components/InfoCard.js new file mode 100644 index 00000000..6b33034e --- /dev/null +++ b/themes/commerce/components/InfoCard.js @@ -0,0 +1,33 @@ +import { useRouter } from 'next/router' +import Card from './Card' +import SocialButton from './SocialButton' +import MenuGroupCard from './MenuGroupCard' +import LazyImage from '@/components/LazyImage' +import { siteConfig } from '@/lib/config' + +/** + * 社交信息卡 + * @param {*} props + * @returns + */ +export function InfoCard(props) { + const { className, siteInfo } = props + const router = useRouter() + return ( + +
      { + router.push('/') + }} + > + {/* eslint-disable-next-line @next/next/no-img-element */} + +
      +
      {siteConfig('AUTHOR')}
      +
      {siteConfig('BIO')}
      + + +
      + ) +} diff --git a/themes/commerce/components/JumpToCommentButton.js b/themes/commerce/components/JumpToCommentButton.js new file mode 100644 index 00000000..fb007712 --- /dev/null +++ b/themes/commerce/components/JumpToCommentButton.js @@ -0,0 +1,29 @@ +import React from 'react' +import CONFIG from '../config' + +/** + * 跳转到评论区 + * @returns {JSX.Element} + * @constructor + */ +const JumpToCommentButton = () => { + if (!CONFIG.WIDGET_TO_COMMENT) { + return <> + } + + function navToComment() { + if (document.getElementById('comment')) { + window.scrollTo({ top: document.getElementById('comment').offsetTop, behavior: 'smooth' }) + } + // 兼容性不好 + // const commentElement = document.getElementById('comment') + // if (commentElement) { + // commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }) + } + + return (
      + +
      ) +} + +export default JumpToCommentButton diff --git a/themes/commerce/components/JumpToTopButton.js b/themes/commerce/components/JumpToTopButton.js new file mode 100644 index 00000000..77313f46 --- /dev/null +++ b/themes/commerce/components/JumpToTopButton.js @@ -0,0 +1,25 @@ +import { useGlobal } from '@/lib/global' +import React from 'react' +import CONFIG from '../config' + +/** + * 跳转到网页顶部 + * 当屏幕下滑500像素后会出现该控件 + * @param targetRef 关联高度的目标html标签 + * @param showPercent 是否显示百分比 + * @returns {JSX.Element} + * @constructor + */ +const JumpToTopButton = ({ showPercent = true, percent }) => { + const { locale } = useGlobal() + + if (!CONFIG.WIDGET_TO_TOP) { + return <> + } + return (
      window.scrollTo({ top: 0, behavior: 'smooth' })} > +
      + {showPercent && (
      {percent}
      )} +
      ) +} + +export default JumpToTopButton diff --git a/themes/commerce/components/LatestPostsGroup.js b/themes/commerce/components/LatestPostsGroup.js new file mode 100644 index 00000000..a6d9ace2 --- /dev/null +++ b/themes/commerce/components/LatestPostsGroup.js @@ -0,0 +1,64 @@ +import BLOG from '@/blog.config' +import LazyImage from '@/components/LazyImage' +import { useGlobal } from '@/lib/global' +// import Image from 'next/image' +import Link from 'next/link' +import { useRouter } from 'next/router' + +/** + * 最新文章列表 + * @param posts 所有文章数据 + * @param sliceCount 截取展示的数量 默认6 + * @constructor + */ +const LatestPostsGroup = ({ latestPosts, siteInfo }) => { + // 获取当前路径 + const currentPath = useRouter().asPath + const { locale } = useGlobal() + + if (!latestPosts) { + return <> + } + + return <> +
      +
      + + {locale.COMMON.LATEST_POSTS} +
      +
      + {latestPosts.map(post => { + const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}` + + const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover + + return ( + ( + +
      + +
      +
      +
      +
      {post.title}
      +
      {post.lastEditedDay}
      +
      +
      + + ) + ) + })} + +} +export default LatestPostsGroup diff --git a/themes/commerce/components/LoadingCover.js b/themes/commerce/components/LoadingCover.js new file mode 100644 index 00000000..c6418fad --- /dev/null +++ b/themes/commerce/components/LoadingCover.js @@ -0,0 +1,8 @@ +export default function LoadingCover () { + return (
      +
      + +
      +
      + ) +} diff --git a/themes/commerce/components/LogoBar.js b/themes/commerce/components/LogoBar.js new file mode 100644 index 00000000..925f1063 --- /dev/null +++ b/themes/commerce/components/LogoBar.js @@ -0,0 +1,20 @@ +import Link from 'next/link' +import { siteConfig } from '@/lib/config' +import LazyImage from '@/components/LazyImage'; + +/** + * Logo图标 + * @param {*} props + * @returns + */ +export default function LogoBar (props) { + const { siteInfo } = props + return ( +
      + + + +
      {siteConfig('TITLE')}
      +
      + ); +} diff --git a/themes/commerce/components/MenuBarMobile.js b/themes/commerce/components/MenuBarMobile.js new file mode 100644 index 00000000..d21fbfe5 --- /dev/null +++ b/themes/commerce/components/MenuBarMobile.js @@ -0,0 +1,39 @@ +import React from 'react' +import { useGlobal } from '@/lib/global' +import CONFIG from '../config' +import BLOG from '@/blog.config' +import { MenuItemCollapse } from './MenuItemCollapse' + +export const MenuBarMobile = (props) => { + const { customMenu, customNav } = props + const { locale } = useGlobal() + + let links = [ + // { name: locale.NAV.INDEX, to: '/' || '/', show: true }, + { name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG.MENU_CATEGORY }, + { name: locale.COMMON.TAGS, to: '/tag', show: CONFIG.MENU_TAG }, + { name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG.MENU_ARCHIVE } + // { name: locale.NAV.SEARCH, to: '/search', show: CONFIG.MENU_SEARCH } + ] + + if (customNav) { + links = links.concat(customNav) + } + + // 如果 开启自定义菜单,则不再使用 Page生成菜单。 + if (BLOG.CUSTOM_MENU) { + links = customMenu + } + + if (!links || links.length === 0) { + return null + } + + return ( + + ) +} diff --git a/themes/commerce/components/MenuGroupCard.js b/themes/commerce/components/MenuGroupCard.js new file mode 100644 index 00000000..3b5ac595 --- /dev/null +++ b/themes/commerce/components/MenuGroupCard.js @@ -0,0 +1,51 @@ +import React from 'react' +import Link from 'next/link' +import { useGlobal } from '@/lib/global' +import CONFIG from '../config' + +const MenuGroupCard = (props) => { + const { postCount, categoryOptions, tagOptions } = props + const { locale } = useGlobal() + const archiveSlot =
      {postCount}
      + const categorySlot =
      {categoryOptions?.length}
      + const tagSlot =
      {tagOptions?.length}
      + + const links = [ + { name: locale.COMMON.ARTICLE, to: '/archive', slot: archiveSlot, show: CONFIG.MENU_ARCHIVE }, + { name: locale.COMMON.CATEGORY, to: '/category', slot: categorySlot, show: CONFIG.MENU_CATEGORY }, + { name: locale.COMMON.TAGS, to: '/tag', slot: tagSlot, show: CONFIG.MENU_TAG } + ] + + for (let i = 0; i < links.length; i++) { + if (links[i].id !== i) { + links[i].id = i + } + } + + return ( + + ) +} +export default MenuGroupCard diff --git a/themes/commerce/components/MenuItemCollapse.js b/themes/commerce/components/MenuItemCollapse.js new file mode 100644 index 00000000..ccd9d6bc --- /dev/null +++ b/themes/commerce/components/MenuItemCollapse.js @@ -0,0 +1,54 @@ +import Collapse from '@/components/Collapse' +import Link from 'next/link' +import { useState } from 'react' + +/** + * 折叠菜单 + * @param {*} param0 + * @returns + */ +export const MenuItemCollapse = ({ link }) => { + const [show, changeShow] = useState(false) + const hasSubMenu = link?.subMenus?.length > 0 + + const [isOpen, changeIsOpen] = useState(false) + + const toggleShow = () => { + changeShow(!show) + } + + const toggleOpenSubMenu = () => { + changeIsOpen(!isOpen) + } + + if (!link || !link.show) { + return null + } + + return <> +
      + {!hasSubMenu && + {link?.icon && }{link?.name} + } + {hasSubMenu &&
      + {link?.icon && }{link?.name} + +
      } +
      + + {/* 折叠子菜单 */} + {hasSubMenu && + {link.subMenus.map((sLink, index) => { + return
      + + {link?.icon && } {sLink.title} + +
      + })} +
      } + +} diff --git a/themes/commerce/components/MenuItemDrop.js b/themes/commerce/components/MenuItemDrop.js new file mode 100644 index 00000000..05a6b4e6 --- /dev/null +++ b/themes/commerce/components/MenuItemDrop.js @@ -0,0 +1,43 @@ +import Link from 'next/link' +import { useRouter } from 'next/router' +import { useState } from 'react' + +export const MenuItemDrop = ({ link }) => { + const [show, changeShow] = useState(false) + const hasSubMenu = link?.subMenus?.length > 0 + const selected = useRouter().asPath === link.to + + if (!link || !link.show) { + return null + } + + return
      changeShow(true)} onMouseOut={() => changeShow(false)} className='h-full'> + + {!hasSubMenu && + + {link?.icon && } {link?.name} + {/* {hasSubMenu && } */} + } + + {hasSubMenu && <> +
      + {link?.icon && } {link?.name} + {/* */} +
      + } + + {/* 子菜单 */} + {hasSubMenu &&
        + {link.subMenus.map((sLink, index) => { + return
      • + + {link?.icon &&   }{sLink.title} + +
      • + })} +
      } + +
      +} diff --git a/themes/commerce/components/MenuListSide.js b/themes/commerce/components/MenuListSide.js new file mode 100644 index 00000000..789d07d2 --- /dev/null +++ b/themes/commerce/components/MenuListSide.js @@ -0,0 +1,43 @@ +import React from 'react' +import { useGlobal } from '@/lib/global' +import BLOG from '@/blog.config' +import { MenuItemCollapse } from './MenuItemCollapse' +import CONFIG from '../config' + +export const MenuListSide = (props) => { + const { customNav, customMenu } = props + const { locale } = useGlobal() + + let links = [ + { icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG.MENU_ARCHIVE }, + { icon: 'fas fa-search', name: locale.NAV.SEARCH, to: '/search', show: CONFIG.MENU_SEARCH }, + { icon: 'fas fa-folder', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG.MENU_CATEGORY }, + { icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG.MENU_TAG } + ] + + if (customNav) { + links = customNav.concat(links) + } + + for (let i = 0; i < links.length; i++) { + if (links[i].id !== i) { + links[i].id = i + } + } + + // 如果 开启自定义菜单,则覆盖Page生成的菜单 + if (BLOG.CUSTOM_MENU) { + links = customMenu + } + + if (!links || links.length === 0) { + return null + } + + return ( + + ) +} diff --git a/themes/commerce/components/MenuListTop.js b/themes/commerce/components/MenuListTop.js new file mode 100644 index 00000000..4a07b562 --- /dev/null +++ b/themes/commerce/components/MenuListTop.js @@ -0,0 +1,43 @@ +import React from 'react' +import { useGlobal } from '@/lib/global' +import CONFIG from '../config' +import { MenuItemDrop } from './MenuItemDrop' +import { siteConfig } from '@/lib/config' + +export const MenuListTop = (props) => { + const { customNav, customMenu } = props + const { locale } = useGlobal() + + let links = [ + { id: 1, icon: 'fa-solid fa-house', name: locale.NAV.INDEX, to: '/', show: CONFIG.MENU_INDEX }, + { id: 2, icon: 'fas fa-search', name: locale.NAV.SEARCH, to: '/search', show: CONFIG.MENU_SEARCH }, + { id: 3, icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG.MENU_ARCHIVE } + // { icon: 'fas fa-folder', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG.MENU_CATEGORY }, + // { icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG.MENU_TAG } + ] + + if (customNav) { + links = links.concat(customNav) + } + + for (let i = 0; i < links.length; i++) { + if (links[i].id !== i) { + links[i].id = i + } + } + + // 如果 开启自定义菜单,则覆盖Page生成的菜单 + if (siteConfig('CUSTOM_MENU')) { + links = customMenu + } + + if (!links || links.length === 0) { + return null + } + + return (<> + + ) +} diff --git a/themes/commerce/components/NavButtonGroup.js b/themes/commerce/components/NavButtonGroup.js new file mode 100644 index 00000000..38709213 --- /dev/null +++ b/themes/commerce/components/NavButtonGroup.js @@ -0,0 +1,33 @@ + +import React from 'react' +import Link from 'next/link' + +/** + * 首页导航大按钮组件 + * @param {*} props + * @returns + */ +const NavButtonGroup = (props) => { + const { categoryOptions } = props + if (!categoryOptions || categoryOptions.length === 0) { + return <> + } + + return ( + + ) +} +export default NavButtonGroup diff --git a/themes/commerce/components/PaginationNumber.js b/themes/commerce/components/PaginationNumber.js new file mode 100644 index 00000000..d041fe6c --- /dev/null +++ b/themes/commerce/components/PaginationNumber.js @@ -0,0 +1,107 @@ +import Link from 'next/link' +import { useRouter } from 'next/router' + +/** + * 数字翻页插件 + * @param page 当前页码 + * @param showNext 是否有下一页 + * @returns {JSX.Element} + * @constructor + */ +const PaginationNumber = ({ page, totalPage }) => { + const router = useRouter() + const currentPage = +page + const showNext = page < totalPage + const pagePrefix = router.asPath.split('?')[0].replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') + const pages = generatePages(pagePrefix, page, currentPage, totalPage) + + return ( +
      + {/* 上一页 */} + + + + + + + {pages} + + {/* 下一页 */} + + + + + +
      + ) +} + +function getPageElement(page, currentPage, pagePrefix) { + return ( + ( + + {page} + + ) + ) +} + +function generatePages(pagePrefix, page, currentPage, totalPage) { + const pages = [] + const groupCount = 7 // 最多显示页签数 + if (totalPage <= groupCount) { + for (let i = 1; i <= totalPage; i++) { + pages.push(getPageElement(i, page, pagePrefix)) + } + } else { + pages.push(getPageElement(1, page, pagePrefix)) + const dynamicGroupCount = groupCount - 2 + let startPage = currentPage - 2 + if (startPage <= 1) { + startPage = 2 + } + if (startPage + dynamicGroupCount > totalPage) { + startPage = totalPage - dynamicGroupCount + } + if (startPage > 2) { + pages.push(
      ...
      ) + } + + for (let i = 0; i < dynamicGroupCount; i++) { + if (startPage + i < totalPage) { + pages.push(getPageElement(startPage + i, page, pagePrefix)) + } + } + + if (startPage + dynamicGroupCount < totalPage) { + pages.push(
      ...
      ) + } + + pages.push(getPageElement(totalPage, page, pagePrefix)) + } + return pages +} +export default PaginationNumber diff --git a/themes/commerce/components/PostHeader.js b/themes/commerce/components/PostHeader.js new file mode 100644 index 00000000..acafaf0f --- /dev/null +++ b/themes/commerce/components/PostHeader.js @@ -0,0 +1,79 @@ +import Link from 'next/link' +import TagItemMini from './TagItemMini' +import { useGlobal } from '@/lib/global' +import BLOG from '@/blog.config' +import NotionIcon from '@/components/NotionIcon' +import LazyImage from '@/components/LazyImage' +import { formatDateFmt } from '@/lib/formatDate' + +export default function PostHeader({ post, siteInfo }) { + const { locale } = useGlobal() + + if (!post) { + return <> + } + const headerImage = post?.pageCover ? post.pageCover : siteInfo?.pageCover + + return ( + + ) +} diff --git a/themes/commerce/components/Progress.js b/themes/commerce/components/Progress.js new file mode 100644 index 00000000..8cb9fe0e --- /dev/null +++ b/themes/commerce/components/Progress.js @@ -0,0 +1,44 @@ +import React, { useEffect, useState } from 'react' +import { isBrowser } from '@/lib/utils' + +/** + * 顶部页面阅读进度条 + * @returns {JSX.Element} + * @constructor + */ +const Progress = ({ targetRef, showPercent = true }) => { + const currentRef = targetRef?.current || targetRef + const [percent, changePercent] = useState(0) + const scrollListener = () => { + const target = currentRef || (isBrowser && document.getElementById('article-wrapper')) + if (target) { + const clientHeight = target.clientHeight + const scrollY = window.pageYOffset + const fullHeight = clientHeight - window.outerHeight + let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) + if (per > 100) per = 100 + if (per < 0) per = 0 + changePercent(per) + } + } + + useEffect(() => { + document.addEventListener('scroll', scrollListener) + return () => document.removeEventListener('scroll', scrollListener) + }, []) + + return ( +
      +
      + {showPercent && ( +
      {percent}%
      + )} +
      +
      + ) +} + +export default Progress diff --git a/themes/commerce/components/RightFloatArea.js b/themes/commerce/components/RightFloatArea.js new file mode 100644 index 00000000..06fef20e --- /dev/null +++ b/themes/commerce/components/RightFloatArea.js @@ -0,0 +1,42 @@ +import throttle from 'lodash.throttle' +import { useCallback, useEffect, useState } from 'react' +import FloatDarkModeButton from './FloatDarkModeButton' +import JumpToTopButton from './JumpToTopButton' + +/** + * 悬浮在右下角的按钮,当页面向下滚动100px时会出现 + * @param {*} param0 + * @returns + */ +export default function RightFloatArea({ floatSlot }) { + const [showFloatButton, switchShow] = useState(false) + const scrollListener = useCallback(throttle(() => { + const targetRef = document.getElementById('wrapper') + const clientHeight = targetRef?.clientHeight + const scrollY = window.pageYOffset + const fullHeight = clientHeight - window.outerHeight + let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) + if (per > 100) per = 100 + const shouldShow = scrollY > 100 && per > 0 + + // 右下角显示悬浮按钮 + if (shouldShow !== showFloatButton) { + switchShow(shouldShow) + } + }, 200)) + + useEffect(() => { + document.addEventListener('scroll', scrollListener) + return () => document.removeEventListener('scroll', scrollListener) + }, []) + + return ( +
      +
      + + {floatSlot} + +
      +
      + ) +} diff --git a/themes/commerce/components/SearchDrawer.js b/themes/commerce/components/SearchDrawer.js new file mode 100644 index 00000000..c7ec88a7 --- /dev/null +++ b/themes/commerce/components/SearchDrawer.js @@ -0,0 +1,36 @@ +import { Router } from 'next/router' +import { useImperativeHandle, useRef } from 'react' +import SearchInput from './SearchInput' +const SearchDrawer = ({ cRef, slot }) => { + const searchDrawer = useRef() + const searchInputRef = useRef() + useImperativeHandle(cRef, () => { + return { + show: () => { + searchDrawer?.current?.classList?.remove('hidden') + searchInputRef?.current?.focus() + } + } + }) + const hidden = () => { + searchDrawer?.current?.classList?.add('hidden') + } + Router.events.on('routeChangeComplete', (...args) => { + hidden() + }) + return ( +
      +
      +
      + + {slot} +
      +
      + + {/* 背景蒙版 */} +
      +
      + ) +} + +export default SearchDrawer diff --git a/themes/commerce/components/SearchInput.js b/themes/commerce/components/SearchInput.js new file mode 100644 index 00000000..462c58b3 --- /dev/null +++ b/themes/commerce/components/SearchInput.js @@ -0,0 +1,106 @@ +import { useRouter } from 'next/router' +import { useImperativeHandle, useRef, useState } from 'react' +import { useGlobal } from '@/lib/global' +let lock = false + +const SearchInput = props => { + const { currentSearch, cRef, className } = props + const [onLoading, setLoadingState] = useState(false) + const router = useRouter() + const searchInputRef = useRef() + const { locale } = useGlobal() + useImperativeHandle(cRef, () => { + return { + focus: () => { + searchInputRef?.current?.focus() + } + } + }) + + const handleSearch = () => { + const key = searchInputRef.current.value + if (key && key !== '') { + setLoadingState(true) + router.push({ pathname: '/search/' + key }).then(r => { + setLoadingState(false) + }) + // location.href = '/search/' + key + } else { + router.push({ pathname: '/' }).then(r => {}) + } + } + const handleKeyUp = e => { + if (e.keyCode === 13) { + // 回车 + handleSearch(searchInputRef.current.value) + } else if (e.keyCode === 27) { + // ESC + cleanSearch() + } + } + const cleanSearch = () => { + searchInputRef.current.value = '' + } + + const [showClean, setShowClean] = useState(false) + const updateSearchKey = val => { + if (lock) { + return + } + searchInputRef.current.value = val + + if (val) { + setShowClean(true) + } else { + setShowClean(false) + } + } + function lockSearchInput () { + lock = true + } + + function unLockSearchInput () { + lock = false + } + + return ( +
      + updateSearchKey(e.target.value)} + defaultValue={currentSearch || ''} + /> + +
      + +
      + + {showClean && ( +
      + +
      + )} +
      + ) +} + +export default SearchInput diff --git a/themes/commerce/components/SearchNav.js b/themes/commerce/components/SearchNav.js new file mode 100644 index 00000000..fc393c1b --- /dev/null +++ b/themes/commerce/components/SearchNav.js @@ -0,0 +1,70 @@ +import { useGlobal } from '@/lib/global' +import Link from 'next/link' +import { useEffect, useRef } from 'react' +import Card from './Card' +import SearchInput from './SearchInput' +import TagItemMini from './TagItemMini' + +/** + * 搜索页面的导航 + * @param {*} props + * @returns + */ +export default function SearchNav(props) { + const { tagOptions, categoryOptions } = props + const cRef = useRef(null) + const { locale } = useGlobal() + useEffect(() => { + // 自动聚焦到搜索框 + cRef?.current?.focus() + }, []) + + return <> +
      + + {/* 分类 */} + +
      + + {locale.COMMON.CATEGORY}: +
      +
      + {categoryOptions?.map(category => { + return ( + +
      + + {category.name}({category.count}) +
      + + ) + })} +
      +
      + {/* 标签 */} + +
      + + {locale.COMMON.TAGS}: +
      +
      + {tagOptions?.map(tag => { + return ( +
      + +
      + ) + })} +
      +
      +
      + +} diff --git a/themes/commerce/components/SideBar.js b/themes/commerce/components/SideBar.js new file mode 100644 index 00000000..913ce0a9 --- /dev/null +++ b/themes/commerce/components/SideBar.js @@ -0,0 +1,33 @@ +import { siteConfig } from '@/lib/config' +import LazyImage from '@/components/LazyImage' +import { useRouter } from 'next/router' +import MenuGroupCard from './MenuGroupCard' +import { MenuListSide } from './MenuListSide' + +/** + * 侧边抽屉 + * @param tags + * @param currentTag + * @returns {JSX.Element} + * @constructor + */ +const SideBar = (props) => { + const { siteInfo } = props + const router = useRouter() + return ( + + ) +} + +export default SideBar diff --git a/themes/commerce/components/SideBarDrawer.js b/themes/commerce/components/SideBarDrawer.js new file mode 100644 index 00000000..f457d4a3 --- /dev/null +++ b/themes/commerce/components/SideBarDrawer.js @@ -0,0 +1,52 @@ +import { useRouter } from 'next/router' +import { useEffect } from 'react' + +/** + * 侧边栏抽屉面板,可以从侧面拉出 + * @returns {JSX.Element} + * @constructor + */ +const SideBarDrawer = ({ children, isOpen, onOpen, onClose, className }) => { + const router = useRouter() + useEffect(() => { + const sideBarDrawerRouteListener = () => { + switchSideDrawerVisible(false) + } + router.events.on('routeChangeComplete', sideBarDrawerRouteListener) + return () => { + router.events.off('routeChangeComplete', sideBarDrawerRouteListener) + } + }, [router.events]) + + // 点击按钮更改侧边抽屉状态 + const switchSideDrawerVisible = (showStatus) => { + if (showStatus) { + onOpen && onOpen() + } else { + onClose && onClose() + } + const sideBarDrawer = window.document.getElementById('sidebar-drawer') + const sideBarDrawerBackground = window.document.getElementById('sidebar-drawer-background') + + if (showStatus) { + sideBarDrawer?.classList.replace('-mr-72', 'mr-0') + sideBarDrawerBackground?.classList.replace('hidden', 'block') + } else { + sideBarDrawer?.classList.replace('mr-0', '-mr-72') + sideBarDrawerBackground?.classList.replace('block', 'hidden') + } + } + + return + + } export default Footer diff --git a/themes/commerce/components/Hero.js b/themes/commerce/components/Hero.js index ef50465f..34ddbd57 100644 --- a/themes/commerce/components/Hero.js +++ b/themes/commerce/components/Hero.js @@ -1,65 +1,24 @@ // import Image from 'next/image' -import { useEffect, useState } from 'react' -import Typed from 'typed.js' import CONFIG from '../config' -import NavButtonGroup from './NavButtonGroup' -import { useGlobal } from '@/lib/global' import LazyImage from '@/components/LazyImage' -import { siteConfig } from '@/lib/config' - -let wrapperTop = 0 /** * 顶部全屏大图 * @returns */ const Hero = props => { - const [typed, changeType] = useState() const { siteInfo } = props - const { locale } = useGlobal() - const scrollToWrapper = () => { - window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) - } - const GREETING_WORDS = siteConfig('GREETING_WORDS').split(',') - useEffect(() => { - updateHeaderHeight() - - if (!typed && window && document.getElementById('typed')) { - changeType( - new Typed('#typed', { - strings: GREETING_WORDS, - typeSpeed: 200, - backSpeed: 100, - backDelay: 400, - showCursor: true, - smartBackspace: true - }) - ) - } - - window.addEventListener('resize', updateHeaderHeight) - return () => { - window.removeEventListener('resize', updateHeaderHeight) - } - }) - - function updateHeaderHeight() { - requestAnimationFrame(() => { - const wrapperElement = document.getElementById('wrapper') - wrapperTop = wrapperElement?.offsetTop - }) - } return ( ) diff --git a/themes/commerce/components/LogoBar.js b/themes/commerce/components/LogoBar.js index 925f1063..de5a5bfe 100644 --- a/themes/commerce/components/LogoBar.js +++ b/themes/commerce/components/LogoBar.js @@ -1,5 +1,5 @@ import Link from 'next/link' -import { siteConfig } from '@/lib/config' +// import { siteConfig } from '@/lib/config' import LazyImage from '@/components/LazyImage'; /** @@ -14,7 +14,7 @@ export default function LogoBar (props) { -
      {siteConfig('TITLE')}
      + {/*
      {siteConfig('TITLE')}
      */}
      ); } diff --git a/themes/commerce/components/MenuItemDrop.js b/themes/commerce/components/MenuItemDrop.js index 05a6b4e6..cec4b854 100644 --- a/themes/commerce/components/MenuItemDrop.js +++ b/themes/commerce/components/MenuItemDrop.js @@ -16,14 +16,14 @@ export const MenuItemDrop = ({ link }) => { {!hasSubMenu && - {link?.icon && } {link?.name} + className={`${selected && 'border-b-2 border-[#D2232A]'} h-full flex space-x-1 whitespace-nowrap items-center font-sans menu-link pl-2 pr-4 dark:text-gray-200 no-underline tracking-widest pb-1`}> + {link?.icon && }
      {link?.name}
      {/* {hasSubMenu && } */} } {hasSubMenu && <> -
      - {link?.icon && } {link?.name} +
      + {link?.icon && }
      {link?.name}
      {/* */}
      } diff --git a/themes/commerce/components/MenuListSide.js b/themes/commerce/components/MenuListSide.js index 789d07d2..a60ba77e 100644 --- a/themes/commerce/components/MenuListSide.js +++ b/themes/commerce/components/MenuListSide.js @@ -18,7 +18,7 @@ export const MenuListSide = (props) => { if (customNav) { links = customNav.concat(links) } - + for (let i = 0; i < links.length; i++) { if (links[i].id !== i) { links[i].id = i diff --git a/themes/commerce/components/TopNavBar.js b/themes/commerce/components/TopNavBar.js index 00a232fa..c2bf6065 100644 --- a/themes/commerce/components/TopNavBar.js +++ b/themes/commerce/components/TopNavBar.js @@ -17,7 +17,6 @@ export default function TopNavBar(props) { const { customNav, customMenu } = props const [isOpen, changeShow] = useState(false) const collapseRef = useRef(null) - let windowTop = 0 const { locale } = useGlobal() @@ -43,19 +42,17 @@ export default function TopNavBar(props) { } }, []) - const throttleMs = 200 + const throttleMs = 150 const scrollTrigger = throttle(() => { const scrollS = window.scrollY - const nav = document.querySelector('#navbar') + const nav = document.querySelector('#top-navbar') - const narrowNav = scrollS >= windowTop || scrollS > 200 + const narrowNav = scrollS > 50 if (narrowNav) { - nav && nav.classList.replace('h-24', 'h-16') - windowTop = scrollS + nav && nav.classList.replace('h-24', 'h-14') } else { - nav && nav.classList.replace('h-16', 'h-24') - windowTop = scrollS + nav && nav.classList.replace('h-14', 'h-24') } }, throttleMs) @@ -68,34 +65,32 @@ export default function TopNavBar(props) { return null } - return ( -
      + return
      - {/* 移动端折叠菜单 */} - -
      - collapseRef.current?.updateCollapseHeight(param)} /> -
      -
      + {/* 移动端折叠菜单 */} + +
      + collapseRef.current?.updateCollapseHeight(param)} /> +
      +
      - {/* 导航栏菜单 */} -