Merge branch 'tangly1024:main' into main

This commit is contained in:
Sebastian
2023-09-17 17:22:00 +08:00
committed by GitHub
24 changed files with 846 additions and 498 deletions

View File

@@ -1,2 +1,2 @@
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
NEXT_PUBLIC_VERSION=4.0.13
NEXT_PUBLIC_VERSION=4.0.15

View File

@@ -26,6 +26,7 @@ module.exports = {
}
},
rules: {
semi: 0,
'react/no-unknown-property': 'off', // <style jsx>
'react/prop-types': 'off',
'space-before-function-paren': 0,

View File

@@ -1,39 +0,0 @@
## 利用GitHub Actions每天定时给百度推送链接提高收录率 ##
name: baidupush
# 两种触发方式一、push代码二、每天国际标准时间23点北京时间+8即早上7点运行
on:
# push:
schedule:
- cron: '0 23 * * *' # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule
workflow_dispatch:
inputs:
unconditional-invoking:
description: 'baidupush unconditionally'
type: boolean
required: true
default: true
# on:
# schedule:
# - cron: '*/5 * * * *' # 每5分钟一次测试用
jobs:
bot:
runs-on: ubuntu-latest # 运行环境为最新版的Ubuntu
steps:
- name: 'Checkout codes' # 步骤一,获取仓库代码
uses: actions/checkout@v2
# - name: 'Run baiduPush' # 步骤二执行sh命令文件
# run: npm install && npm run baiduPush # 运行目录是仓库根目录
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: install requests
run: pip install requests
- name: baidupush
run: npm run baidupush

61
.github/workflows/pushUrl.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
## 利用GitHub Actions每天定时给百度推送链接提高收录率 ##
name: pushUrl
# 两种触发方式一、push代码二、每天国际标准时间23点北京时间+8即早上7点运行
on:
push:
schedule:
- cron: '0 23 * * *' # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule
workflow_dispatch:
inputs:
unconditional-invoking:
description: 'push url unconditionally'
type: boolean
required: true
default: true
# on:
# schedule:
# - cron: '*/5 * * * *' # 每5分钟一次测试用
jobs:
bot:
runs-on: ubuntu-latest # 运行环境为最新版的Ubuntu
steps:
- name: 'Checkout codes' # 步骤一,获取仓库代码
uses: actions/checkout@v2
# - name: 'Run baiduPush' # 步骤二执行sh命令文件
# run: npm install && npm run baiduPush # 运行目录是仓库根目录
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install requests
run: pip install requests
- name: Push
env:
URL: ${{ secrets.URL }}
BAIDU_TOKEN: ${{ secrets.BAIDU_TOKEN }}
BING_API_KEY: ${{ secrets.BING_API_KEY }}
run: |
if [ -n "$URL" ]; then
if [ -n "$BAIDU_TOKEN" ]; then
python pushUrl.py --url $URL --baidu_token $BAIDU_TOKEN
else
echo "请前往 Github Action Secrets 配置 BAIDU_TOKEN:"
echo "详情参见: 'https://www.ghlcode.cn/fe032806-5362-4d82-b746-a0b26ce8b9d9'"
fi
if [ -n "$BING_API_KEY" ]; then
python pushUrl.py --url $URL --bing_api_key $BING_API_KEY
else
echo "请前往 Github Action Secrets 配置 BING_API_KEY:"
echo "详情参见: 'https://www.ghlcode.cn/fe032806-5362-4d82-b746-a0b26ce8b9d9'"
fi
else
echo "请前往 Github Action Secrets 配置 URL:"
echo "详情参见: 'https://www.ghlcode.cn/fe032806-5362-4d82-b746-a0b26ce8b9d9'"
fi

View File

@@ -1,18 +0,0 @@
import re
import ssl
import requests
import argparse
if __name__ == '__main__':
ssl._create_default_https_context = ssl._create_unverified_context
parser = argparse.ArgumentParser(description='parse sitemap')
parser.add_argument('url', help='The url of your website')
args = parser.parse_args()
url = f'https://{args.url}/sitemap.xml'
result = requests.get(url)
big = re.findall('<loc>(.*?)</loc>', result.content.decode('utf-8'), re.S)
for i in big:
# print(i)
op_xml_txt = open('urls.txt', 'a')
op_xml_txt.write('%s\n' % i)

View File

@@ -1,12 +0,0 @@
#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
# 解析sitemap.xml 记得换成你自己的域名注意检查是否包含www
python baidupush.py 'www.ghlerrix.cn'
# 百度链接推送换成自己的token和域名
curl -H 'Content-Type:text/plain' --data-binary @urls.txt "http://data.zz.baidu.com/urls?site=https://www.ghlerrix.cn&token=oUldnU4HZvSTlh0e"
rm -rf urls.txt # 删除文件

View File

@@ -13,6 +13,6 @@ export default function WWAds({ orientation = 'vertical', sticky = false, classN
}
return (
<div className={`wwads-cn ${orientation === 'vertical' ? 'wwads-vertical' : 'wwads-horizontal'} ${sticky ? 'wwads-sticky' : ''} z-30 ${className || ''}`} data-id={BLOG.AD_WWADS_ID}></div>
<div className={`wwads-cn ${orientation === 'vertical' ? 'wwads-vertical' : 'wwads-horizontal'} ${sticky ? 'wwads-sticky' : ''} z-10 ${className || ''}`} data-id={BLOG.AD_WWADS_ID}></div>
)
}

View File

@@ -49,8 +49,8 @@ function getLatestPosts({ allPages, from, latestPostCount }) {
const allPosts = allPages?.filter(page => page.type === 'Post' && page.status === 'Published')
const latestPosts = Object.create(allPosts).sort((a, b) => {
const dateA = new Date(a?.lastEditedDay || a?.publishDate)
const dateB = new Date(b?.lastEditedDay || b?.publishDate)
const dateA = new Date(a?.lastEditedDate || a?.publishDate)
const dateB = new Date(b?.lastEditedDate || b?.publishDate)
return dateB - dateA
})
return latestPosts.slice(0, latestPostCount)

View File

@@ -63,6 +63,7 @@ export async function getPageWithRetry(id, from, retryAttempts = 3) {
/**
* 获取到的blockMap删除不需要的字段
* 并且对于页面内容进行特殊处理比如文件url格式化
* @param {*} id 页面ID
* @param {*} pageBlock 页面元素
* @param {*} slice 截取数量
@@ -72,6 +73,7 @@ function filterPostBlocks(id, pageBlock, slice) {
const clonePageBlock = deepClone(pageBlock)
let count = 0
// 循环遍历文档的每个block
for (const i in clonePageBlock?.block) {
const b = clonePageBlock?.block[i]
if (slice && slice > 0 && count > slice) {
@@ -99,6 +101,13 @@ function filterPostBlocks(id, pageBlock, slice) {
}
}
// 如果是文件或嵌入式PDF需要重新加密签名
if ((b?.value?.type === 'file' || b?.value?.type === 'pdf') && b?.value?.properties?.source?.[0][0]) {
const oldUrl = b?.value?.properties?.source?.[0][0]
const newUrl = `https://notion.so/signed/${encodeURIComponent(oldUrl)}?table=block&id=${b?.value?.id}`
b.value.properties.source[0][0] = newUrl
}
delete b?.role
delete b?.value?.version
delete b?.value?.created_by_table

View File

@@ -61,7 +61,9 @@ const mapImgUrl = (img, block, type = 'block', from) => {
}
// Notion 图床转换为永久地址
if (ret.indexOf('secure.notion-static.com') > 0 && (BLOG.IMG_URL_TYPE === 'Notion' || type !== 'block')) {
const isNotionImg = ret.indexOf('secure.notion-static.com') > 0 || ret.indexOf('prod-files-secure') > 0
const isImgBlock = BLOG.IMG_URL_TYPE === 'Notion' || type !== 'block'
if (isNotionImg && isImgBlock) {
ret = BLOG.NOTION_HOST + '/image/' + encodeURIComponent(ret) + '?table=' + type + '&id=' + block.id
}

View File

@@ -1,6 +1,6 @@
{
"name": "notion-next",
"version": "4.0.13",
"version": "4.0.15",
"homepage": "https://github.com/tangly1024/NotionNext.git",
"license": "MIT",
"repository": {
@@ -18,8 +18,7 @@
"start": "next start",
"post-build": "next-sitemap --config next-sitemap.config.js",
"export": "next build && next-sitemap --config next-sitemap.config.js && next export",
"bundle-report": "ANALYZE=true yarn build",
"baidupush": "bash baidupush.sh"
"bundle-report": "ANALYZE=true yarn build"
},
"dependencies": {
"@giscus/react": "^2.2.6",

96
pushUrl.py Normal file
View File

@@ -0,0 +1,96 @@
import random
import re
import ssl
import time
import requests
import argparse
ssl._create_default_https_context = ssl._create_unverified_context
# 每日推送限额,可根据实际情况修改
QUOTA = 100
def parse_stiemap(site):
site = f'{site}/sitemap.xml'
try:
result = requests.get(site)
big = re.findall('<loc>(.*?)</loc>', result.content.decode('utf-8'), re.S)
return list(big)
except:
print('请检查你的url是否有误。')
print('正确的应是完整的域名包含https://且不包含sitemap.xml, 如下所示:')
print('正确的示例: https://ghlcode.cn')
print('详情参见: https://ghlcode.cn/fe032806-5362-4d82-b746-a0b26ce8b9d9')
def push_to_bing(site, urls, api_key):
endpoint = f"https://ssl.bing.com/webmaster/api.svc/json/SubmitUrlbatch?apikey={api_key}"
payload = {
"siteUrl": site,
"urlList": urls
}
try:
response = requests.post(endpoint, json=payload)
result = response.json()
if response.status_code == 200:
print("成功推送到Bing.")
elif "ErrorCode" in result:
print("推送到Bing出现错误错误信息为", result["Message"])
except Exception as e:
print("An error occurred:", e)
def push_to_baidu(site, urls, token):
api_url = f"http://data.zz.baidu.com/urls?site={site}&token={token}"
payload = "\n".join(urls)
headers = {"Content-Type": "text/plain"}
try:
response = requests.post(api_url, data=payload, headers=headers)
result = response.json()
if "success" in result and result["success"]:
print("成功推送到百度.")
elif "error" in result:
print("推送到百度出现错误,错误信息为:", result["message"])
else:
print("Unknown response from Baidu:", result)
except Exception as e:
print("An error occurred:", e)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='parse sitemap')
parser.add_argument('--url', type=str, default=None, help='The url of your website')
parser.add_argument('--bing_api_key', type=str, default=None, help='your bing api key')
parser.add_argument('--baidu_token', type=str, default=None, help='Your baidu push token')
args = parser.parse_args()
# 获取当前的时间戳作为随机种子
current_timestamp = int(time.time())
random.seed(current_timestamp)
if args.url:
# 解析urls
urls = parse_stiemap(args.url)
if urls is not None:
# 判断当前urls数量是否超过额度若超过则取当日最大值默认为100可根据实际情况修改
if len(urls) > QUOTA:
urls = random.sample(urls, QUOTA)
# 推送bing
if args.bing_api_key:
print('正在推送至必应,请稍后……')
push_to_bing(args.url, urls, args.bing_api_key)
# 推送百度
if args.baidu_token:
print('正在推送至百度,请稍后……')
push_to_baidu(args.url, urls, args.baidu_token)
else:
print('请前往 Github Action Secrets 配置 URL')
print('详情参见: https://ghlcode.cn/fe032806-5362-4d82-b746-a0b26ce8b9d9')

View File

@@ -28,6 +28,7 @@ export default function CategoryBar(props) {
setScrollRight(!scrollRight)
}
}
return <div id='category-bar' className={`flex flex-nowrap justify-between items-center h-12 mb-4 space-x-2 w-full lg:bg-white dark:lg:bg-[#1e1e1e]
${border ? 'lg:border lg:hover:border dark:lg:border-gray-800 hover:border-indigo-600 dark:hover:border-yellow-600 ' : ''} py-2 lg:px-2 rounded-xl transition-colors duration-200`}>
@@ -54,7 +55,8 @@ export default function CategoryBar(props) {
*/
const MenuItem = ({ href, name }) => {
const router = useRouter()
const selected = router.pathname === href
const { category } = router.query
const selected = category === name
return <div className={`whitespace-nowrap mr-2 duration-200 transition-all font-bold px-2 py-0.5 rounded-md text-gray-900 dark:text-white hover:text-white hover:bg-indigo-600 dark:hover:bg-yellow-600 ${selected ? 'text-white bg-indigo-600 dark:bg-yellow-600' : ''}`}>
<Link href={href}>{name}</Link>
</div>

View File

@@ -17,18 +17,24 @@ import CONFIG from '../config'
*/
const Hero = props => {
return (
<div id="hero-wrapper" className='recent-top-post-group w-full overflow-hidden select-none px-5 mb-4'>
<div
id="hero-wrapper"
className="recent-top-post-group w-full overflow-hidden select-none px-5 mb-4"
>
<div
id="hero"
style={{ zIndex: 1 }}
className={
'animate__animated animate__fadeIn animate__fast recent-post-top rounded-[12px] 2xl:px-5 recent-top-post-group max-w-[86rem] overflow-x-scroll w-full mx-auto flex-row flex-nowrap flex xl:space-x-3 relative'
}
>
{/* 左侧banner组 */}
<BannerGroup {...props} />
<div id="hero" style={{ zIndex: 1 }} className={'animate__animated animate__fadeIn animate__fast recent-post-top rounded-[12px] xl:px-5 recent-top-post-group max-w-[86rem] overflow-x-scroll w-full mx-auto flex-row flex-nowrap flex xl:space-x-3 relative'} >
{/* 左侧banner组 */}
<BannerGroup {...props} />
{/* 右侧置顶文章组 */}
<TopGroup {...props} />
</div>
</div>
{/* 右侧置顶文章组 */}
<TopGroup {...props} />
</div>
</div>
)
}
@@ -38,13 +44,16 @@ const Hero = props => {
*/
function BannerGroup(props) {
return (
// 左侧英雄区
<div id='bannerGroup' className='flex flex-col justify-between flex-1 mr-2 max-w-[42rem]'>
{/* 动图 */}
<Banner {...props} />
{/* 导航分类 */}
<GroupMenu />
</div>
// 左侧英雄区
<div
id="bannerGroup"
className="flex flex-col justify-between flex-1 mr-2 max-w-[42rem]"
>
{/* 动图 */}
<Banner {...props} />
{/* 导航分类 */}
<GroupMenu />
</div>
)
}
@@ -64,25 +73,43 @@ function Banner(props) {
router.push(`${BLOG.SUB_PATH}/${randomPost?.slug}`)
}
return <div id='banners' onClick={handleClickBanner} className="hidden xl:flex xl:flex-col group h-full bg-white dark:bg-[#1e1e1e] rounded-xl border dark:border-gray-700 mb-3 relative overflow-hidden">
<div id='banner-title' className='flex flex-col absolute top-10 left-10'>
<div className='text-4xl font-bold mb-3 dark:text-white'>{CONFIG.HERO_TITLE_1}<br />{CONFIG.HERO_TITLE_2}</div>
<div className='text-xs text-gray-600 dark:text-gray-200'>{CONFIG.HERO_TITLE_3}</div>
return (
<div
id="banners"
onClick={handleClickBanner}
className="hidden xl:flex xl:flex-col group h-full bg-white dark:bg-[#1e1e1e] rounded-xl border dark:border-gray-700 mb-3 relative overflow-hidden"
>
<div id="banner-title" className="flex flex-col absolute top-10 left-10">
<div className="text-4xl font-bold mb-3 dark:text-white">
{CONFIG.HERO_TITLE_1}
<br />
{CONFIG.HERO_TITLE_2}
</div>
{/* 斜向滚动的图标 */}
<TagsGroupBar />
{/* 遮罩 */}
<div id='banner-cover' style={{ backdropFilter: 'blur(15px)' }} className={'rounded-xl overflow-hidden opacity-0 group-hover:opacity-100 duration-300 transition-all bg-[#4259efdd] dark:bg-[#dca846] dark:text-white cursor-pointer absolute w-full h-full top-0 flex justify-start items-center'}>
<div className='ml-12 -translate-x-32 group-hover:translate-x-0 duration-300 transition-all ease-in'>
<div className='text-7xl text-white font-extrabold'>随便逛逛</div>
<div className='-ml-3 text-gray-300'><ArrowSmallRight className={'w-24 h-24 stroke-2'} /></div>
</div>
<div className="text-xs text-gray-600 dark:text-gray-200">
{CONFIG.HERO_TITLE_3}
</div>
</div>
{/* 斜向滚动的图标 */}
<TagsGroupBar />
{/* 遮罩 */}
<div
id="banner-cover"
style={{ backdropFilter: 'blur(15px)' }}
className={
'rounded-xl overflow-hidden opacity-0 group-hover:opacity-100 duration-300 transition-all bg-[#4259efdd] dark:bg-[#dca846] dark:text-white cursor-pointer absolute w-full h-full top-0 flex justify-start items-center'
}
>
<div className="ml-12 -translate-x-32 group-hover:translate-x-0 duration-300 transition-all ease-in">
<div className="text-7xl text-white font-extrabold">随便逛逛</div>
<div className="-ml-3 text-gray-300">
<ArrowSmallRight className={'w-24 h-24 stroke-2'} />
</div>
</div>
</div>
</div>
)
}
/**
@@ -93,20 +120,42 @@ function TagsGroupBar() {
const groupIcons = CONFIG.GROUP_ICONS.concat(CONFIG.GROUP_ICONS)
return (
<div className="tags-group-all flex -rotate-[30deg] h-full">
<div className="tags-group-wrapper flex flex-nowrap absolute top-16">
{groupIcons?.map((g, index) => {
return (<div key={index} className="tags-group-icon-pair ml-6 select-none">
<div style={{ background: g.color_1 }} className={'tags-group-icon w-28 h-28 rounded-3xl flex items-center justify-center text-white text-lg font-bold shadow-md'}>
<LazyImage priority={true} src={g.img_1} title={g.title_1} className='w-2/3 hidden xl:block' />
</div>
<div style={{ background: g.color_2 }} className={'tags-group-icon mt-5 w-28 h-28 rounded-3xl flex items-center justify-center text-white text-lg font-bold shadow-md'}>
<LazyImage priority={true} src={g.img_2} title={g.title_2} className='w-2/3 hidden xl:block' />
</div>
</div>)
})}
<div className="tags-group-all flex -rotate-[30deg] h-full">
<div className="tags-group-wrapper flex flex-nowrap absolute top-16">
{groupIcons?.map((g, index) => {
return (
<div key={index} className="tags-group-icon-pair ml-6 select-none">
<div
style={{ background: g.color_1 }}
className={
'tags-group-icon w-28 h-28 rounded-3xl flex items-center justify-center text-white text-lg font-bold shadow-md'
}
>
<LazyImage
priority={true}
src={g.img_1}
title={g.title_1}
className="w-2/3 hidden xl:block"
/>
</div>
<div
style={{ background: g.color_2 }}
className={
'tags-group-icon mt-5 w-28 h-28 rounded-3xl flex items-center justify-center text-white text-lg font-bold shadow-md'
}
>
<LazyImage
priority={true}
src={g.img_2}
title={g.title_2}
className="w-2/3 hidden xl:block"
/>
</div>
</div>
</div>
)
})}
</div>
</div>
)
}
@@ -116,37 +165,45 @@ function TagsGroupBar() {
*/
function GroupMenu() {
return (
<div className="h-[165px] select-none xl:h-20 flex flex-col justify-between xl:space-y-0 xl:flex-row w-28 lg:w-48 xl:w-full xl:flex-nowrap xl:space-x-3">
<Link href={CONFIG.HERO_CATEGORY_1?.url} className="group relative overflow-hidden bg-gradient-to-r from-blue-500 to-blue-400 flex h-20 justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in">
<div className="font-bold lg:text-lg pl-5 relative -mt-2">
{CONFIG.HERO_CATEGORY_1?.title}
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
</div>
<div className='hidden lg:block absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
<i className="fa-solid fa-star text-4xl"></i>
</div>
</Link>
<Link href={CONFIG.HERO_CATEGORY_2?.url} className="group relative overflow-hidden bg-gradient-to-r from-red-500 to-yellow-500 flex h-20 justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in">
<div className="font-bold lg:text-lg pl-5 relative -mt-2">
{CONFIG.HERO_CATEGORY_2?.title}
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
</div>
<div className='hidden lg:block absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
<i className="fa-solid fa-fire-flame-curved text-4xl"></i>
</div>
</Link>
{/* 第三个标签在小屏上不显示 */}
<Link href={CONFIG.HERO_CATEGORY_3?.url} className="group relative overflow-hidden bg-gradient-to-r from-teal-300 to-cyan-300 hidden h-20 xl:flex justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in">
<div className="font-bold text-lg pl-5 relative -mt-2">
{CONFIG.HERO_CATEGORY_3?.title}
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
</div>
<div className='absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0'>
<i className="fa-solid fa-book-bookmark text-4xl "></i>
</div>
</Link>
<div className="h-[165px] select-none xl:h-20 flex flex-col justify-between xl:space-y-0 xl:flex-row w-28 lg:w-48 xl:w-full xl:flex-nowrap xl:space-x-3">
<Link
href={CONFIG.HERO_CATEGORY_1?.url}
className="group relative overflow-hidden bg-gradient-to-r from-blue-500 to-blue-400 flex h-20 justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in"
>
<div className="font-bold lg:text-lg pl-5 relative -mt-2">
{CONFIG.HERO_CATEGORY_1?.title}
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
</div>
<div className="hidden lg:block absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0">
<i className="fa-solid fa-star text-4xl"></i>
</div>
</Link>
<Link
href={CONFIG.HERO_CATEGORY_2?.url}
className="group relative overflow-hidden bg-gradient-to-r from-red-500 to-yellow-500 flex h-20 justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in"
>
<div className="font-bold lg:text-lg pl-5 relative -mt-2">
{CONFIG.HERO_CATEGORY_2?.title}
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
</div>
<div className="hidden lg:block absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0">
<i className="fa-solid fa-fire-flame-curved text-4xl"></i>
</div>
</Link>
{/* 第三个标签在小屏上不显示 */}
<Link
href={CONFIG.HERO_CATEGORY_3?.url}
className="group relative overflow-hidden bg-gradient-to-r from-teal-300 to-cyan-300 hidden h-20 xl:flex justify-start items-center text-white rounded-xl xl:hover:w-1/2 xl:w-1/3 transition-all duration-500 ease-in"
>
<div className="font-bold text-lg pl-5 relative -mt-2">
{CONFIG.HERO_CATEGORY_3?.title}
<span className="absolute -bottom-0.5 left-5 w-5 h-0.5 bg-white rounded-full"></span>
</div>
<div className="absolute right-6 duration-700 ease-in-out transition-all scale-[2] translate-y-6 rotate-12 opacity-20 group-hover:opacity-80 group-hover:scale-100 group-hover:translate-y-0 group-hover:rotate-0">
<i className="fa-solid fa-book-bookmark text-4xl "></i>
</div>
</Link>
</div>
)
}
@@ -164,24 +221,40 @@ function TopGroup(props) {
const topPosts = getTopPosts({ latestPosts, allNavPages })
return (
<div id='hero-right-wrapper' onMouseLeave={handleMouseLeave} className='flex-1 relative w-full'>
{/* 置顶推荐文章 */}
<div id='top-group' className='w-full flex space-x-3 xl:space-x-0 xl:grid xl:grid-cols-3 xl:gap-3 xl:h-[342px]'>
{topPosts?.map((p, index) => {
return <Link href={`${BLOG.SUB_PATH}/${p?.slug}`} key={index}>
<div className='cursor-pointer h-[164px] group relative flex flex-col w-52 xl:w-full overflow-hidden shadow bg-white dark:bg-black dark:text-white rounded-xl'>
<LazyImage priority={index === 0} className='h-24 object-cover' alt={p?.title} src={p?.pageCoverThumbnail || siteInfo?.pageCover} />
<div className='group-hover:text-indigo-600 dark:group-hover:text-yellow-600 line-clamp-2 overflow-hidden m-2 font-semibold'>{p?.title}</div>
{/* hover 悬浮的 ‘荐’ 字 */}
<div className='opacity-0 group-hover:opacity-100 -translate-x-4 group-hover:translate-x-0 duration-200 transition-all absolute -top-2 -left-2 bg-indigo-600 dark:bg-yellow-600 text-white rounded-xl overflow-hidden pr-2 pb-2 pl-4 pt-4 text-xs'>
</div>
</div>
</Link>
})}
</div>
<TodayCard cRef={todayCardRef} />
</div>
<div
id="hero-right-wrapper"
onMouseLeave={handleMouseLeave}
className="flex-1 relative w-full"
>
{/* 置顶推荐文章 */}
<div
id="top-group"
className="w-full flex space-x-3 xl:space-x-0 xl:grid xl:grid-cols-3 xl:gap-3 xl:h-[342px]"
>
{topPosts?.map((p, index) => {
return (
<Link href={`${BLOG.SUB_PATH}/${p?.slug}`} key={index}>
<div className="cursor-pointer h-[164px] group relative flex flex-col w-52 xl:w-full overflow-hidden shadow bg-white dark:bg-black dark:text-white rounded-xl">
<LazyImage
priority={index === 0}
className="h-24 object-cover"
alt={p?.title}
src={p?.pageCoverThumbnail || siteInfo?.pageCover}
/>
<div className="group-hover:text-indigo-600 dark:group-hover:text-yellow-600 line-clamp-2 overflow-hidden m-2 font-semibold">
{p?.title}
</div>
{/* hover 悬浮的 ‘荐’ 字 */}
<div className="opacity-0 group-hover:opacity-100 -translate-x-4 group-hover:translate-x-0 duration-200 transition-all absolute -top-2 -left-2 bg-indigo-600 dark:bg-yellow-600 text-white rounded-xl overflow-hidden pr-2 pb-2 pl-4 pt-4 text-xs">
</div>
</div>
</Link>
)
})}
</div>
<TodayCard cRef={todayCardRef} />
</div>
)
}
@@ -190,7 +263,10 @@ function TopGroup(props) {
*/
function getTopPosts({ latestPosts, allNavPages }) {
// 默认展示最近更新
if (!CONFIG.HERO_RECOMMEND_POST_TAG || CONFIG.HERO_RECOMMEND_POST_TAG === '') {
if (
!CONFIG.HERO_RECOMMEND_POST_TAG ||
CONFIG.HERO_RECOMMEND_POST_TAG === ''
) {
return latestPosts
}
@@ -231,8 +307,8 @@ function TodayCard({ cRef }) {
const [isCoverUp, setIsCoverUp] = useState(true)
/**
* 外部可以调用此方法
*/
* 外部可以调用此方法
*/
useImperativeHandle(cRef, () => {
return {
coverUp: () => {
@@ -242,37 +318,73 @@ function TodayCard({ cRef }) {
})
/**
* 点击更多
* @param {*} e
*/
* 点击更多
* @param {*} e
*/
function handleClickMore(e) {
e.stopPropagation()
setIsCoverUp(false)
}
/**
* 点击卡片跳转的链接
* @param {*} e
*/
* 点击卡片跳转的链接
* @param {*} e
*/
function handleCardClick(e) {
router.push(CONFIG.HERO_TITLE_LINK)
}
return <div id='today-card' className={`${isCoverUp ? ' ' : 'pointer-events-none'} overflow-hidden absolute hidden xl:flex flex-1 flex-col h-full top-0 w-full`}>
<div id='card-body' onClick={handleCardClick} className={`${isCoverUp ? 'opacity-100 cursor-pointer' : 'opacity-0 transform scale-110 pointer-events-none'} shadow transition-all duration-200 today-card h-full bg-[#0E57D5] rounded-xl relative overflow-hidden flex items-end`}>
<div id='today-card-info' className='z-10 flex justify-between w-full relative text-white p-10 items-end'>
<div className='flex flex-col'>
<div className='text-xs font-light'>{CONFIG.HERO_TITLE_4}</div>
<div className='text-3xl font-bold'>{CONFIG.HERO_TITLE_5}</div>
</div>
<div onClick={handleClickMore} className={`'${isCoverUp ? '' : 'hidden pointer-events-none '} flex items-center px-3 h-10 justify-center bg-[#425aef] hover:bg-[#4259efcb] transition-colors duration-100 rounded-3xl`}>
<PlusSmall className={'w-6 h-6 mr-2 bg-white rounded-full stroke-indigo-400'} />
<div id='more' className='select-none'>更多推荐</div>
</div>
return (
<div
id="today-card"
className={`${
isCoverUp ? ' ' : 'pointer-events-none'
} overflow-hidden absolute hidden xl:flex flex-1 flex-col h-full top-0 w-full`}
>
<div
id="card-body"
onClick={handleCardClick}
className={`${
isCoverUp
? 'opacity-100 cursor-pointer'
: 'opacity-0 transform scale-110 pointer-events-none'
} shadow transition-all duration-200 today-card h-full bg-[#0E57D5] rounded-xl relative overflow-hidden flex items-end`}
>
<div
id="today-card-info"
className="z-10 flex justify-between w-full relative text-white p-10 items-end"
>
<div className="flex flex-col">
<div className="text-xs font-light">{CONFIG.HERO_TITLE_4}</div>
<div className="text-3xl font-bold">{CONFIG.HERO_TITLE_5}</div>
</div>
<div
onClick={handleClickMore}
className={`'${
isCoverUp ? '' : 'hidden pointer-events-none '
} flex items-center px-3 h-10 justify-center bg-[#425aef] hover:bg-[#4259efcb] transition-colors duration-100 rounded-3xl`}
>
<PlusSmall
className={'w-6 h-6 mr-2 bg-white rounded-full stroke-indigo-400'}
/>
<div id="more" className="select-none">
更多推荐
</div>
<div id='today-card-cover' className={`${isCoverUp ? '' : ' pointer-events-none'} cursor-pointer today-card-cover absolute w-full h-full top-0`} style={{ background: "url('https://bu.dusays.com/2023/03/12/640dcd3a1b146.png') no-repeat center /cover" }}></div>
</div>
</div>
<div
id="today-card-cover"
className={`${
isCoverUp ? '' : ' pointer-events-none'
} cursor-pointer today-card-cover absolute w-full h-full top-0`}
style={{
background:
"url('https://bu.dusays.com/2023/03/12/640dcd3a1b146.png') no-repeat center /cover"
}}
></div>
</div>
</div>
)
}
export default Hero

View File

@@ -1,7 +1,7 @@
import CONFIG from './config'
import CommonHead from '@/components/CommonHead'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import Footer from './components/Footer'
import SideRight from './components/SideRight'
import NavBar from './components/NavBar'
@@ -41,38 +41,55 @@ import { AdSlot } from '@/components/GoogleAdsense'
* @constructor
*/
const LayoutBase = props => {
const { children, headerSlot, slotTop, slotRight, siteInfo, className, meta } = props
const {
children,
headerSlot,
slotTop,
slotRight,
siteInfo,
className,
meta
} = props
return (
<div id='theme-heo' className='bg-[#f7f9fe] dark:bg-[#18171d] h-full min-h-screen flex flex-col'>
{/* SEO信息 */}
<CommonHead meta={meta} />
<Style />
<div
id="theme-heo"
className="bg-[#f7f9fe] dark:bg-[#18171d] h-full min-h-screen flex flex-col"
>
{/* SEO信息 */}
<CommonHead meta={meta} />
<Style />
{/* 顶部嵌入 导航栏首页放hero文章页放文章详情 */}
{headerSlot}
{/* 顶部嵌入 导航栏首页放hero文章页放文章详情 */}
{headerSlot}
{/* 主区块 */}
<main id="wrapper-outer" className={'flex-grow w-full max-w-[86rem] mx-auto relative md:px-5'}>
{/* 主区块 */}
<main
id="wrapper-outer"
className={'flex-grow w-full max-w-[86rem] mx-auto relative md:px-5'}
>
<div
id="container-inner"
className={
'w-full mx-auto lg:flex lg:space-x-4 justify-center relative z-10'
}
>
<div className={`w-full h-auto ${className || ''}`}>
{/* 主区上部嵌入 */}
{slotTop}
{children}
</div>
<div id="container-inner" className={'w-full mx-auto lg:flex lg:space-x-4 justify-center relative z-10'} >
<div className={`w-full h-auto ${className || ''}`}>
{/* 主区上部嵌入 */}
{slotTop}
{children}
</div>
<div>
{/* 主区快右侧 */}
{slotRight}
</div>
</div>
</main>
{/* 页脚 */}
<Footer title={siteInfo?.title || BLOG.TITLE} />
<div className="hidden xl:block">
{/* 主区快右侧 */}
{slotRight}
</div>
</div>
</main>
{/* 页脚 */}
<Footer title={siteInfo?.title || BLOG.TITLE} />
</div>
)
}
@@ -82,28 +99,40 @@ const LayoutBase = props => {
* @param {*} props
* @returns
*/
const LayoutIndex = (props) => {
const headerSlot = <header>
{/* 顶部导航 */}
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
{/* 通知横幅 */}
<NoticeBar />
<Hero {...props} />
<div className='max-w-[86rem] mx-auto px-3'>
<WWAds className='w-full' orientation='horizontal' />
</div>
const LayoutIndex = props => {
const headerSlot = (
<header>
{/* 顶部导航 */}
<div id="nav-bar-wrapper" className="h-16">
<NavBar {...props} />
</div>
{/* 通知横幅 */}
<NoticeBar />
<Hero {...props} />
<div className="max-w-[86rem] mx-auto px-3">
<WWAds className="w-full" orientation="horizontal" />
</div>
</header>
)
// 右侧栏 用户信息+标签列表
const slotRight = <SideRight {...props} />
return <LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
<div id='post-outer-wrapper' className='px-5 md:px-0'>
{/* 文章分类条 */}
<CategoryBar {...props} />
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
</div>
return (
<LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
<div id="post-outer-wrapper" className="px-5 md:px-0">
{/* 文章分类条 */}
<CategoryBar {...props} />
{BLOG.POST_LIST_STYLE === 'page'
? (
<BlogPostListPage {...props} />
)
: (
<BlogPostListScroll {...props} />
)}
</div>
</LayoutBase>
)
}
/**
@@ -111,21 +140,33 @@ const LayoutIndex = (props) => {
* @param {*} props
* @returns
*/
const LayoutPostList = (props) => {
const LayoutPostList = props => {
// 右侧栏
const slotRight = <SideRight {...props} />
const headerSlot = <header>
{/* 顶部导航 */}
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
const headerSlot = (
<header>
{/* 顶部导航 */}
<div id="nav-bar-wrapper" className="h-16">
<NavBar {...props} />
</div>
</header>
)
return <LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
<div id='post-outer-wrapper' className='px-5 md:px-0'>
{/* 文章分类条 */}
<CategoryBar {...props} />
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
</div>
return (
<LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
<div id="post-outer-wrapper" className="px-5 md:px-0">
{/* 文章分类条 */}
<CategoryBar {...props} />
{BLOG.POST_LIST_STYLE === 'page'
? (
<BlogPostListPage {...props} />
)
: (
<BlogPostListScroll {...props} />
)}
</div>
</LayoutBase>
)
}
/**
@@ -137,11 +178,15 @@ const LayoutSearch = props => {
const { keyword } = props
const router = useRouter()
const currentSearch = keyword || router?.query?.s
const headerSlot = <header className='post-bg'>
{/* 顶部导航 */}
<div id='nav-bar-wrapper'><NavBar {...props} /></div>
<PostHeader {...props} />
const headerSlot = (
<header className="post-bg">
{/* 顶部导航 */}
<div id="nav-bar-wrapper">
<NavBar {...props} />
</div>
<PostHeader {...props} />
</header>
)
useEffect(() => {
// 高亮搜索结果
@@ -159,15 +204,29 @@ const LayoutSearch = props => {
}
}, [])
return (
<LayoutBase {...props} currentSearch={currentSearch} headerSlot={headerSlot}>
<div id='post-outer-wrapper' className='px-5 md:px-0'>
{!currentSearch
? <SearchNav {...props} />
: <div id="posts-wrapper">
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
</div>}
</div>
</LayoutBase>
<LayoutBase
{...props}
currentSearch={currentSearch}
headerSlot={headerSlot}
>
<div id="post-outer-wrapper" className="px-5 md:px-0">
{!currentSearch
? (
<SearchNav {...props} />
)
: (
<div id="posts-wrapper">
{BLOG.POST_LIST_STYLE === 'page'
? (
<BlogPostListPage {...props} />
)
: (
<BlogPostListScroll {...props} />
)}
</div>
)}
</div>
</LayoutBase>
)
}
@@ -176,34 +235,40 @@ const LayoutSearch = props => {
* @param {*} props
* @returns
*/
const LayoutArchive = (props) => {
const LayoutArchive = props => {
const { archivePosts } = props
// 右侧栏
const slotRight = <SideRight {...props} />
const headerSlot = <header>
{/* 顶部导航 */}
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
const headerSlot = (
<header>
{/* 顶部导航 */}
<div id="nav-bar-wrapper" className="h-16">
<NavBar {...props} />
</div>
</header>
)
// 归档页顶部显示条,如果是默认归档则不显示。分类详情页显示分类列表,标签详情页显示当前标签
return <LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
<div className='p-5 rounded-xl border dark:border-gray-600 max-w-6xl w-full bg-white dark:bg-[#1e1e1e]'>
{/* 文章分类条 */}
<CategoryBar {...props} border={false} />
return (
<LayoutBase {...props} slotRight={slotRight} headerSlot={headerSlot}>
<div className="p-5 rounded-xl border dark:border-gray-600 max-w-6xl w-full bg-white dark:bg-[#1e1e1e]">
{/* 文章分类条 */}
<CategoryBar {...props} border={false} />
<div className='px-3'>
{Object.keys(archivePosts).map(archiveTitle => (
<BlogPostArchive
key={archiveTitle}
posts={archivePosts[archiveTitle]}
archiveTitle={archiveTitle}
/>
))}
</div>
<div className="px-3">
{Object.keys(archivePosts).map(archiveTitle => (
<BlogPostArchive
key={archiveTitle}
posts={archivePosts[archiveTitle]}
archiveTitle={archiveTitle}
/>
))}
</div>
</div>
</LayoutBase>
)
}
/**
@@ -215,74 +280,97 @@ const LayoutSlug = props => {
const { post, lock, validPassword } = props
const { locale } = useGlobal()
const [hasCode, setHasCode] = useState(false)
useEffect(() => {
const hasCode = document.querySelectorAll('[class^="language-"]').length > 0
setHasCode(hasCode)
}, [])
// 右侧栏
const slotRight = <SideRight {...props} />
const headerSlot = <header
data-aos="fade-up"
data-aos-duration="300"
data-aos-once="false"
data-aos-anchor-placement="top-bottom"
className='post-bg'>
{/* 顶部导航 */}
<div id='nav-bar-wrapper'><NavBar {...props} /></div>
<PostHeader {...props} />
const headerSlot = (
<header
data-aos="fade-up"
data-aos-duration="300"
data-aos-once="false"
data-aos-anchor-placement="top-bottom"
className="post-bg"
>
{/* 顶部导航 */}
<div id="nav-bar-wrapper">
<NavBar {...props} />
</div>
<PostHeader {...props} />
</header>
)
return (
<LayoutBase {...props} headerSlot={headerSlot} showCategory={false} showTag={false} slotRight={slotRight}>
<div className="w-full max-w-5xl lg:hover:shadow lg:border rounded-2xl lg:px-2 lg:py-4 bg-white dark:bg-[#18171d] dark:border-gray-600 article">
<LayoutBase
{...props}
headerSlot={headerSlot}
showCategory={false}
showTag={false}
slotRight={slotRight}
>
<div className={`w-full xl:max-w-5xl ${hasCode ? 'xl:w-[73.15vw]' : ''} lg:hover:shadow lg:border rounded-2xl lg:px-2 lg:py-4 bg-white dark:bg-[#18171d] dark:border-gray-600 article`}>
{lock && <ArticleLock validPassword={validPassword} />}
{lock && <ArticleLock validPassword={validPassword} />}
{!lock && (
<div
id="article-wrapper"
className="overflow-x-auto flex-grow mx-auto md:w-full md:px-5 "
>
<article
data-aos="fade-up"
data-aos-duration="300"
data-aos-once="false"
data-aos-anchor-placement="top-bottom"
itemScope
itemType="https://schema.org/Movie"
className="subpixel-antialiased overflow-y-hidden"
>
{/* Notion文章主体 */}
<section className="px-5 justify-center mx-auto">
<WWAds orientation="horizontal" className="w-full" />
{post && <NotionPage post={post} />}
<WWAds orientation="horizontal" className="w-full" />
</section>
{!lock && <div id="article-wrapper" className="overflow-x-auto flex-grow mx-auto md:w-full md:px-5 ">
{/* 分享 */}
<ShareBar post={post} />
{post?.type === 'Post' && (
<div className="px-5">
{/* 版权 */}
<ArticleCopyright {...props} />
{/* 文章推荐 */}
<ArticleRecommend {...props} />
{/* 上一篇\下一篇文章 */}
<ArticleAdjacent {...props} />
</div>
)}
</article>
<article
data-aos="fade-up"
data-aos-duration="300"
data-aos-once="false"
data-aos-anchor-placement="top-bottom"
itemScope itemType="https://schema.org/Movie" className="subpixel-antialiased overflow-y-hidden" >
{/* Notion文章主体 */}
<section className='px-5 justify-center mx-auto'>
<WWAds orientation='horizontal' className='w-full'/>
{post && <NotionPage post={post} />}
<WWAds orientation='horizontal' className='w-full'/>
</section>
<div className={`${commentEnable && post ? '' : 'hidden'}`}>
<hr className="my-4 border-dashed" />
{/* 分享 */}
<ShareBar post={post} />
{post?.type === 'Post' && <div className='px-5'>
{/* 版权 */}
<ArticleCopyright {...props} />
{/* 文章推荐 */}
<ArticleRecommend {...props} />
{/* 上一篇\下一篇文章 */}
<ArticleAdjacent {...props} />
</div>}
</article>
<div className={`${commentEnable && post ? '' : 'hidden'}`}>
<hr className='my-4 border-dashed' />
{/* 评论互动 */}
<div className="duration-200 overflow-x-auto px-5">
<div className='text-2xl dark:text-white'><i className='fas fa-comment mr-1' />{locale.COMMON.COMMENTS}</div>
<Comment frontMatter={post} className='' />
<div className='py-2'>
<AdSlot/>
</div>
</div>
</div>
</div>}
{/* 评论互动 */}
<div className="duration-200 overflow-x-auto px-5">
<div className="text-2xl dark:text-white">
<i className="fas fa-comment mr-1" />
{locale.COMMON.COMMENTS}
</div>
<Comment frontMatter={post} className="" />
<div className="py-2">
<AdSlot />
</div>
</div>
</div>
<FloatTocButton {...props} />
</LayoutBase>
</div>
)}
</div>
<FloatTocButton {...props} />
</LayoutBase>
)
}
@@ -295,59 +383,69 @@ const Layout404 = props => {
const { meta, siteInfo } = props
const { onLoading } = useGlobal()
return (
<div id='theme-heo' className='bg-[#f7f9fe] h-full min-h-screen flex flex-col'>
{/* 网页SEO */}
<CommonHead meta={meta} siteInfo={siteInfo} />
<Style />
{/* 顶部嵌入 导航栏首页放hero文章页放文章详情 */}
<header>
{/* 顶部导航 */}
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
</header>
{/* 主区块 */}
<main id="wrapper-outer" className={'flex-grow max-w-4xl w-screen mx-auto px-5'}>
<div id="error-wrapper" className={'w-full mx-auto justify-center'} >
<Transition
show={!onLoading}
appear={true}
enter="transition ease-in-out duration-700 transform order-first"
enterFrom="opacity-0 translate-y-16"
enterTo="opacity-100"
leave="transition ease-in-out duration-300 transform"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 -translate-y-16"
unmount={false}
>
{/* 404卡牌 */}
<div className='error-content flex flex-col md:flex-row w-full mt-12 h-[30rem] md:h-96 justify-center items-center bg-white border rounded-3xl'>
{/* 左侧动图 */}
<LazyImage className="error-img h-60 md:h-full p-4" src={'https://bu.dusays.com/2023/03/03/6401a7906aa4a.gif'}></LazyImage>
{/* 右侧文字 */}
<div className='error-info flex-1 flex flex-col justify-center items-center space-y-4'>
<h1 className='error-title font-extrabold md:text-9xl text-7xl'>404</h1>
<div>请尝试站内搜索寻找文章</div>
<Link href='/'>
<button className='bg-blue-500 p-2 text-white shadow rounded-lg hover:bg-blue-600 hover:shadow-md duration-200 transition-all'>回到主页</button>
</Link>
</div>
</div>
{/* 404页面底部显示最新文章 */}
<div className='mt-12'>
<LatestPostsGroup {...props} />
</div>
</Transition>
</div>
</main>
<div
id="theme-heo"
className="bg-[#f7f9fe] h-full min-h-screen flex flex-col"
>
{/* 网页SEO */}
<CommonHead meta={meta} siteInfo={siteInfo} />
<Style />
{/* 顶部嵌入 导航栏首页放hero文章页放文章详情 */}
<header>
{/* 顶部导航 */}
<div id="nav-bar-wrapper" className="h-16">
<NavBar {...props} />
</div>
</header>
{/* 主区块 */}
<main
id="wrapper-outer"
className={'flex-grow max-w-4xl w-screen mx-auto px-5'}
>
<div id="error-wrapper" className={'w-full mx-auto justify-center'}>
<Transition
show={!onLoading}
appear={true}
enter="transition ease-in-out duration-700 transform order-first"
enterFrom="opacity-0 translate-y-16"
enterTo="opacity-100"
leave="transition ease-in-out duration-300 transform"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 -translate-y-16"
unmount={false}
>
{/* 404卡牌 */}
<div className="error-content flex flex-col md:flex-row w-full mt-12 h-[30rem] md:h-96 justify-center items-center bg-white border rounded-3xl">
{/* 左侧动图 */}
<LazyImage
className="error-img h-60 md:h-full p-4"
src={'https://bu.dusays.com/2023/03/03/6401a7906aa4a.gif'}
></LazyImage>
{/* 右侧文字 */}
<div className="error-info flex-1 flex flex-col justify-center items-center space-y-4">
<h1 className="error-title font-extrabold md:text-9xl text-7xl">
404
</h1>
<div>请尝试站内搜索寻找文章</div>
<Link href="/">
<button className="bg-blue-500 p-2 text-white shadow rounded-lg hover:bg-blue-600 hover:shadow-md duration-200 transition-all">
回到主页
</button>
</Link>
</div>
</div>
{/* 404页面底部显示最新文章 */}
<div className="mt-12">
<LatestPostsGroup {...props} />
</div>
</Transition>
</div>
</main>
</div>
)
}
@@ -359,34 +457,50 @@ const Layout404 = props => {
const LayoutCategoryIndex = props => {
const { categoryOptions } = props
const { locale } = useGlobal()
const headerSlot = <header>
{/* 顶部导航 */}
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
const headerSlot = (
<header>
{/* 顶部导航 */}
<div id="nav-bar-wrapper" className="h-16">
<NavBar {...props} />
</div>
</header>
)
return (
<LayoutBase {...props} className='mt-8' headerSlot={headerSlot}>
<div id='category-outer-wrapper' className='px-5 md:px-0'>
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
{locale.COMMON.CATEGORY}
<LayoutBase {...props} className="mt-8" headerSlot={headerSlot}>
<div id="category-outer-wrapper" className="px-5 md:px-0">
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
{locale.COMMON.CATEGORY}
</div>
<div
id="category-list"
className="duration-200 flex flex-wrap m-10 justify-center"
>
{categoryOptions.map(category => {
return (
<Link
key={category.name}
href={`/category/${category.name}`}
passHref
legacyBehavior
>
<div
className={
'group mr-5 mb-5 flex flex-nowrap items-center border bg-white text-2xl rounded-xl dark:hover:text-white px-4 cursor-pointer py-3 hover:text-white hover:bg-indigo-600 transition-all hover:scale-110 duration-150'
}
>
<HashTag className={'w-5 h-5 stroke-gray-500 stroke-2'} />
{category.name}
<div className="bg-[#f1f3f8] ml-1 px-2 rounded-lg group-hover:text-indigo-600 ">
{category.count}
</div>
</div>
<div id="category-list" className="duration-200 flex flex-wrap m-10 justify-center">
{categoryOptions.map(category => {
return (
<Link key={category.name} href={`/category/${category.name}`} passHref legacyBehavior>
<div className={'group mr-5 mb-5 flex flex-nowrap items-center border bg-white text-2xl rounded-xl dark:hover:text-white px-4 cursor-pointer py-3 hover:text-white hover:bg-indigo-600 transition-all hover:scale-110 duration-150'}>
<HashTag className={'w-5 h-5 stroke-gray-500 stroke-2'} />
{category.name}
<div className='bg-[#f1f3f8] ml-1 px-2 rounded-lg group-hover:text-indigo-600 '>
{category.count}
</div>
</div>
</Link>
)
})}
</div>
</div>
</LayoutBase>
</Link>
)
})}
</div>
</div>
</LayoutBase>
)
}
@@ -398,33 +512,49 @@ const LayoutCategoryIndex = props => {
const LayoutTagIndex = props => {
const { tagOptions } = props
const { locale } = useGlobal()
const headerSlot = <header>
{/* 顶部导航 */}
<div id='nav-bar-wrapper' className='h-16'><NavBar {...props} /></div>
const headerSlot = (
<header>
{/* 顶部导航 */}
<div id="nav-bar-wrapper" className="h-16">
<NavBar {...props} />
</div>
</header>
)
return (
<LayoutBase {...props} className='mt-8' headerSlot={headerSlot}>
<div id='tag-outer-wrapper' className='px-5 md:px-0'>
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
{locale.COMMON.TAGS}
<LayoutBase {...props} className="mt-8" headerSlot={headerSlot}>
<div id="tag-outer-wrapper" className="px-5 md:px-0">
<div className="text-4xl font-extrabold dark:text-gray-200 mb-5">
{locale.COMMON.TAGS}
</div>
<div
id="tag-list"
className="duration-200 flex flex-wrap space-x-5 space-y-5 m-10 justify-center"
>
{tagOptions.map(tag => {
return (
<Link
key={tag.name}
href={`/tag/${tag.name}`}
passHref
legacyBehavior
>
<div
className={
'group flex flex-nowrap items-center border bg-white text-2xl rounded-xl dark:hover:text-white px-4 cursor-pointer py-3 hover:text-white hover:bg-indigo-600 transition-all hover:scale-110 duration-150'
}
>
<HashTag className={'w-5 h-5 stroke-gray-500 stroke-2'} />
{tag.name}
<div className="bg-[#f1f3f8] ml-1 px-2 rounded-lg group-hover:text-indigo-600 ">
{tag.count}
</div>
</div>
<div id="tag-list" className="duration-200 flex flex-wrap space-x-5 space-y-5 m-10 justify-center">
{tagOptions.map(tag => {
return (
<Link key={tag.name} href={`/tag/${tag.name}`} passHref legacyBehavior>
<div className={'group flex flex-nowrap items-center border bg-white text-2xl rounded-xl dark:hover:text-white px-4 cursor-pointer py-3 hover:text-white hover:bg-indigo-600 transition-all hover:scale-110 duration-150'}>
<HashTag className={'w-5 h-5 stroke-gray-500 stroke-2'} />
{tag.name}
<div className='bg-[#f1f3f8] ml-1 px-2 rounded-lg group-hover:text-indigo-600 '>
{tag.count}
</div>
</div>
</Link>
)
})}
</div>
</div>
</LayoutBase>
</Link>
)
})}
</div>
</div>
</LayoutBase>
)
}

View File

@@ -5,60 +5,65 @@
* @returns
*/
const Style = () => {
return <style jsx global>{`
body {
background-color: #f7f9fe;
return (
<style jsx global>{`
body {
background-color: #f7f9fe;
overflow-x: hidden;
}
}
// 公告栏中的字体固定白色
#theme-heo #announcement-content .notion{
// 公告栏中的字体固定白色
#theme-heo #announcement-content .notion {
color: white;
}
}
::-webkit-scrollbar-thumb {
::-webkit-scrollbar-thumb {
background: rgba(60, 60, 67, 0.4);
border-radius: 8px;
cursor: pointer;
}
}
::-webkit-scrollbar {
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
}
.today-card-cover {
#more {
white-space: nowrap;
}
.today-card-cover {
-webkit-mask-image: linear-gradient(to top, transparent 5%, black 70%);
mask-image: linear-gradient(to top, transparent 5%, black 70%);
}
mask-image: linear-gradient(to top, transparent 5%, black 70%);
}
.recent-top-post-group::-webkit-scrollbar {
.recent-top-post-group::-webkit-scrollbar {
display: none;
}
.scroll-hidden::-webkit-scrollbar {
display: none;
}
}
* {
.scroll-hidden::-webkit-scrollbar {
display: none;
}
* {
box-sizing: border-box;
}
}
// 标签滚动动画
.tags-group-wrapper {
// 标签滚动动画
.tags-group-wrapper {
animation: rowup 60s linear infinite;
}
@keyframes rowup {
}
@keyframes rowup {
0% {
transform: translateX(0%);
transform: translateX(0%);
}
100% {
transform: translateX(-50%);
transform: translateX(-50%);
}
}
`}</style>
}
`}</style>
)
}
export { Style }

View File

@@ -34,7 +34,7 @@ export default function ArticleDetail(props) {
data-aos-duration="300"
data-aos-once="true"
data-aos-anchor-placement="top-bottom"
className="subpixel-antialiased overflow-y-hidden py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-hexo-black-gray"
className="subpixel-antialiased overflow-y-hidden py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-hexo-black-gray article-padding"
>
{showArticleInfo && <header>
@@ -78,7 +78,7 @@ export default function ArticleDetail(props) {
</header>}
{/* Notion内容主体 */}
<article className='px-1 max-w-3xl mx-auto'>
<article className='mx-auto'>
{post && (<NotionPage post={post} />)}
</article>

View File

@@ -28,10 +28,10 @@ const BlogPostCard = ({ post, showSummary }) => {
data-aos-duration="500"
data-aos-once="true"
data-aos-anchor-placement="top-bottom"
className={`cursor-pointer hover:underline text-3xl ${showPreview ? 'text-center' : ''
className={`cursor-pointer text-3xl ${showPreview ? 'text-center' : ''
} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
<NotionIcon icon={post.pageIcon} /> {post.title}
<NotionIcon icon={post.pageIcon} /> <span className='menu-link'>{post.title}</span>
</Link>
@@ -48,10 +48,10 @@ const BlogPostCard = ({ post, showSummary }) => {
<Link
href={`/category/${post.category}`}
passHref
className="hover:text-blue-500 dark:hover:text-blue-400 cursor-pointer font-light text-sm hover:underline transform">
className="hover:text-blue-500 dark:hover:text-blue-400 cursor-pointer font-light text-sm transform">
<i className="mr-1 fas fa-folder" />
{post.category}
<span className='menu-link'>{post.category}</span>
</Link>
<span className="mx-2">|</span>
@@ -60,8 +60,8 @@ const BlogPostCard = ({ post, showSummary }) => {
<Link
href={`/archive#${formatDateFmt(post?.publishDate, 'yyyy-MM')}`}
passHref
className="hover:text-blue-500 dark:hover:text-blue-400 font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
{post.date?.start_date}
className="hover:text-blue-500 dark:hover:text-blue-400 font-light cursor-pointer text-sm leading-4 mr-3">
<span className='menu-link'>{post.date?.start_date}</span>
</Link>
</div>
<TwikooCommentCount post={post} className='hover:text-blue-500 dark:hover:text-blue-400 hover:underline text-sm'/>

View File

@@ -62,7 +62,7 @@ const SideAreaRight = (props) => {
passHref
className='text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
{locale.COMMON.MORE} <i className='fas fa-angle-right' />
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
</Link>
</div>

View File

@@ -15,6 +15,24 @@ const Style = () => {
background-color: black;
}
.article-padding {
padding: 40px;
}
// 菜单下划线动画
#theme-next .menu-link {
text-decoration: none;
background-image: linear-gradient(#4e80ee, #4e80ee);
background-repeat: no-repeat;
background-position: bottom center;
background-size: 0 2px;
transition: background-size 100ms ease-in-out;
}
#theme-next .menu-link:hover {
background-size: 100% 2px;
color: #4e80ee;
}
`}</style>
}

View File

@@ -1,6 +1,5 @@
import Link from 'next/link'
import BLOG from '@/blog.config'
import formatDate from '@/lib/formatDate'
const BlogPost = ({ post }) => {
return (
@@ -12,7 +11,7 @@ const BlogPost = ({ post }) => {
{post.title}
</h2>
<time className="flex-shrink-0 text-gray-600 dark:text-gray-400">
{formatDate(post?.publishDay || post.createdTime, BLOG.LANG)}
{post?.publishDay}
</time>
</header>
<main>

View File

@@ -36,10 +36,10 @@ const BlogPost = (props) => {
<LazyImage src={pageThumbnail} className='aspect-[16/9] w-full h-full object-cover filter contrast-120' />
<h2 className="text-md absolute left-0 bottom-0 m-4 text-black dark:text-gray-100 text-shadow">
<h2 className="text-md absolute left-0 bottom-0 m-4 text-gray-100 shadow-text">
{post?.title}
</h2>
{post?.category && <div className='text-xs rounded-lg absolute left-0 top-0 m-4 px-2 py-1 bg-black bg-opacity-25 hover:bg-blue-700 hover:text-white duration-200'>
{post?.category && <div className='text-xs rounded-lg absolute left-0 top-0 m-4 px-2 py-1 bg-gray-200 dark:bg-black dark:bg-opacity-25 hover:bg-blue-700 hover:text-white duration-200'>
<Link href={`/category/${post?.category}`}>
{post?.category}
</Link>

View File

@@ -13,7 +13,7 @@ import LogoBar from './LogoBar'
*/
const BottomNav = props => {
return <>
<div id="bottom-nav" style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }} className={'z-20 px-4 hidden glassmorphism md:fixed bottom-0 w-screen py-4 md:flex flex-row justify-between items-center'}>
<div id="bottom-nav" className={'dark:bg-black dark:bg-opacity-50z-20 px-4 hidden glassmorphism md:fixed bottom-0 w-screen py-4 md:flex flex-row justify-between items-center'}>
{/* 左侧logo文字栏 */}
<LogoBar {...props}/>
{/* 右下角菜单栏 */}

View File

@@ -18,7 +18,6 @@ import ShareBar from '@/components/ShareBar'
import Link from 'next/link'
import { Transition } from '@headlessui/react'
import BottomNav from './components/BottomNav'
import { saveDarkModeToCookies } from '@/themes/theme'
import Modal from './components/Modal'
import { Style } from './style'
import replaceSearchResult from '@/components/Mark'
@@ -36,29 +35,13 @@ export const usePlogGlobal = () => useContext(ThemeGlobalPlog)
*/
const LayoutBase = props => {
const { children, topSlot, meta } = props
const { onLoading, updateDarkMode } = useGlobal()
const { onLoading } = useGlobal()
const [showModal, setShowModal] = useState(false)
const [modalContent, setModalContent] = useState(null)
// 用户手动设置主题
const setDarkMode = () => {
saveDarkModeToCookies(true)
updateDarkMode(true)
const htmlElement = document.getElementsByTagName('html')[0]
htmlElement.classList?.remove('light')
htmlElement.classList?.add('dark')
}
// plog主题默认 深色模式
useEffect(() => {
setTimeout(() => {
setDarkMode()
}, 100)
}, [])
return (
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full bg-black min-h-screen'>
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full dark:bg-black min-h-screen'>
{/* SEO相关 */}
<CommonHead meta={meta}/>
<Style/>