mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-15 15:09:25 +00:00
Merge branch 'tangly1024:main' into main
This commit is contained in:
@@ -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
|
||||
@@ -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,
|
||||
|
||||
39
.github/workflows/baidupush.yml
vendored
39
.github/workflows/baidupush.yml
vendored
@@ -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
61
.github/workflows/pushUrl.yml
vendored
Normal 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
|
||||
|
||||
18
baidupush.py
18
baidupush.py
@@ -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)
|
||||
12
baidupush.sh
12
baidupush.sh
@@ -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 # 删除文件
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
96
pushUrl.py
Normal 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')
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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'/>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}/>
|
||||
{/* 右下角菜单栏 */}
|
||||
|
||||
@@ -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/>
|
||||
|
||||
Reference in New Issue
Block a user