调试模式

This commit is contained in:
tangly1024
2022-03-15 17:25:56 +08:00
parent a15fc196b2
commit 8a92e14db6
15 changed files with 259 additions and 93 deletions

View File

@@ -8,7 +8,7 @@ const BLOG = {
KEYWORDS: 'Notion, 博客', // 网站关键词 英文逗号隔开 KEYWORDS: 'Notion, 博客', // 网站关键词 英文逗号隔开
NOTION_PAGE_ID: process.env.NOTION_PAGE_ID || '02ab3b8678004aa69e9e415905ef32a5', // Important page_idDuplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5 NOTION_PAGE_ID: process.env.NOTION_PAGE_ID || '02ab3b8678004aa69e9e415905ef32a5', // Important page_idDuplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5
NOTION_ACCESS_TOKEN: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public NOTION_ACCESS_TOKEN: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public
DEBUG_BUTTON: true, // 是否显示调试按钮,可以用来调试不同的主题和样式配置 DEBUG: JSON.parse(process.env.NEXT_PUBLIC_DEBUG) || false, // 是否显示调试按钮
THEME: process.env.NEXT_PUBLIC_THEME || 'next', // 主题, 支持 ['Next','Hexo',"Fukasawa','Medium'] THEME: process.env.NEXT_PUBLIC_THEME || 'next', // 主题, 支持 ['Next','Hexo',"Fukasawa','Medium']
LANG: 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more. LANG: 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more.

View File

@@ -1,50 +0,0 @@
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
import { useState } from 'react'
/**
*
* @returns 调试面板
*/
export function DebugButton () {
const [show, setShow] = useState(false)
const GlobalConfig = useGlobal()
const { theme, setTheme } = GlobalConfig
const allThemes = Object.keys(ThemeMap)
function toggleShow () {
setShow(!show)
}
/**
* 切换主题
*/
function changeTheme () {
const currentIndex = allThemes.indexOf(theme)
const newIndex = currentIndex < allThemes.length - 1 ? currentIndex + 1 : 0
setTheme(allThemes[newIndex])
}
return <>
<div className={`w-full text-sm font-sans h-72 p-5 bg-white fixed right-0 bottom-0 z-40 shadow-card duration-200 ${show ? '' : '-bottom-72'}`}>
<div className='flex space-x-1'>
<div className='font-bold'>当前主题:</div>
<div>{theme}</div>
</div>
<div className='flex space-x-1'>
<div className='font-bold'>所有主题:</div>
<div>{allThemes.join(',')}</div>
</div>
<div className='flex space-x-1'>
<div className='bg-blue-500 text-white p-2 cursor-pointer' onClick={changeTheme}>更换主题</div>
</div>
<div>
<div className='font-bold w-18'>所有配置:</div>
<div><p>{JSON.stringify(GlobalConfig)}</p></div>
</div>
</div>
<div className="fixed right-20 bottom-12 z-50">
<div className="bg-gray-50 text-sm dark:bg-black dark:text-white shadow-2xl p-2.5 rounded-md bg-opacity-75 cursor-pointer" onClick={toggleShow}>调试按钮</div>
</div>
</>
}

138
components/DebugPanel.js Normal file
View File

@@ -0,0 +1,138 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
import { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
import Select from './Select'
/**
*
* @returns 调试面板
*/
export function DebugPanel () {
const [show, setShow] = useState(false)
const GlobalConfig = useGlobal()
const router = useRouter()
const { theme, setTheme } = GlobalConfig
const allThemes = Object.keys(ThemeMap)
const themeOptions = []
allThemes.forEach(t => {
themeOptions.push({ value: t, text: t })
})
function toggleShow () {
setShow(!show)
}
function switchTheme () {
const currentIndex = allThemes.indexOf(theme)
const newIndex = currentIndex < allThemes.length - 1 ? currentIndex + 1 : 0
changeTheme(allThemes[newIndex])
}
useEffect(() => {
const theme = router.query.theme
if (theme && allThemes.indexOf(theme) > -1) {
changeTheme(theme)
}
})
/**
* 切换主题
*/
function changeTheme (theme) {
router.query.theme = ''
setTheme(theme)
}
function filterResult (text) {
switch (text) {
case 'true':
return <span className='text-green-500'>true</span>
case 'false':
return <span className='text-red-500'>false</span>
case '':
return '-'
}
return text
}
return (
<>
{/* 调试按钮 */}
<div
className={`${
show ? 'right-96' : ''
} fixed right-0 bottom-36 duration-200 z-50`}
>
<div
style={{ writingMode: 'vertical-lr' }}
className="bg-black text-white shadow-2xl p-2.5 rounded-l-xl cursor-pointer"
onClick={toggleShow}
>
{show
? (
<i className="fas fa-times">&nbsp;关闭调试</i>
)
: (
<i className="fas fa-tools">&nbsp;打开调试</i>
)}
</div>
</div>
<div
className={` ${
show ? 'shadow-card' : '-right-96'
} w-96 overflow-y-scroll font-sans h-full p-5 bg-white fixed right-0 bottom-0 z-50 duration-200`}
>
<div className="flex space-x-1 my-12">
<Select
label="主题切换"
value={theme}
options={themeOptions}
onChange={changeTheme}
/>
<div className="p-2 cursor-pointer" onClick={switchTheme}>
<i className="fas fa-sync" />
</div>
</div>
<div>
<div className="font-bold w-18 border-b my-2">
站点配置[blog.config.js]
</div>
<div className="text-xs">
{Object.keys(BLOG).map(k => (
<div key={k} className="justify-between flex py-1">
<span className="bg-blue-400 p-0.5 rounded text-white mr-2">
{k}
</span>
<span className="whitespace-nowrap">
{filterResult(BLOG[k] + '')}
</span>
</div>
))}
</div>
</div>
<div>
<div className="font-bold w-18 border-b my-2">
主题配置{'(config_' + theme + '.js)'}:
</div>
<div className="text-xs">
{Object.keys(ThemeMap[theme].THEME_CONFIG).map(k => (
<>
<div key={k} className="justify-between flex py-1">
<span className="bg-indigo-500 p-0.5 rounded text-white mr-2">
{k}
</span>
<span className="whitespace-nowrap">
{filterResult(ThemeMap[theme].THEME_CONFIG[k] + '')}
</span>
</div>
</>
))}
</div>
</div>
</div>
</>
)
}

40
components/Select.js Normal file
View File

@@ -0,0 +1,40 @@
import React from 'react'
/**
* 下拉单选框
*/
class Select extends React.Component {
constructor (props) {
super(props)
this.handleChange = this.handleChange.bind(this)
}
handleChange (event) {
const { onChange } = this.props
onChange(event.target.value)
}
render () {
return (
<div className='py-1 space-x-3'>
<label className='text-gray-500'>{this.props.label}</label>
<select value={this.props.value} onChange={this.handleChange} className='border p-1 rounded cursor-pointer'>
{this.props.options?.map(o => (
<option key={o.value} value={o.value}>
{o.text}
</option>
))}
</select>
</div>
)
}
}
Select.defaultProps = {
label: '',
value: '1',
options: [
{ value: '1', text: '选项1' },
{ value: '2', text: '选项2' }
]
}
export default Select

View File

@@ -44,7 +44,7 @@ const SideBarDrawer = ({ children, isOpen, onOpen, onClose, className }) => {
} }
return <div id='sidebar-wrapper' className={' ' + className}> return <div id='sidebar-wrapper' className={' ' + className}>
<div id='sidebar-drawer' className={`${isOpen ? 'ml-0' : '-ml-80'} bg-white dark:bg-gray-900 flex flex-col duration-300 fixed h-full left-0 overflow-y-scroll scroll-hidden top-0 z-50`}> <div id='sidebar-drawer' className={`${isOpen ? 'ml-0' : '-ml-80'} bg-white dark:bg-gray-900 flex flex-col duration-300 fixed h-full left-0 overflow-y-scroll scroll-hidden top-0 z-40`}>
{children} {children}
</div> </div>
{/* 背景蒙版 */} {/* 背景蒙版 */}

View File

@@ -17,7 +17,6 @@ export function GlobalContextProvider ({ children }) {
const [isDarkMode, updateDarkMode] = useState(false) const [isDarkMode, updateDarkMode] = useState(false)
const [onLoading, changeLoadingState] = useState(false) const [onLoading, changeLoadingState] = useState(false)
const [theme, setTheme] = useState(BLOG.THEME) const [theme, setTheme] = useState(BLOG.THEME)
Router.events.on('routeChangeStart', (...args) => { Router.events.on('routeChangeStart', (...args) => {
changeLoadingState(true) changeLoadingState(true)
}) })

View File

@@ -14,7 +14,7 @@ import 'prismjs/themes/prism-okaidia.css'
import 'katex/dist/katex.min.css' import 'katex/dist/katex.min.css'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
import { GlobalContextProvider } from '@/lib/global' import { GlobalContextProvider } from '@/lib/global'
import { DebugButton } from '@/components/DebugButton' import { DebugPanel } from '@/components/DebugPanel'
const Ackee = dynamic(() => import('@/components/Ackee'), { ssr: false }) const Ackee = dynamic(() => import('@/components/Ackee'), { ssr: false })
const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false }) const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false })
@@ -24,7 +24,7 @@ const GoogleAdsense = dynamic(() => import('@/components/GoogleAdsense'), { ssr:
const MyApp = ({ Component, pageProps }) => { const MyApp = ({ Component, pageProps }) => {
return ( return (
<GlobalContextProvider> <GlobalContextProvider>
{BLOG.DEBUG_BUTTON && <DebugButton/>} {BLOG.DEBUG && <DebugPanel/>}
{BLOG.ANALYTICS_ACKEE_TRACKER && <Ackee />} {BLOG.ANALYTICS_ACKEE_TRACKER && <Ackee />}
{BLOG.ANALYTICS_GOOGLE_ID && <Gtag />} {BLOG.ANALYTICS_GOOGLE_ID && <Gtag />}
{JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && <Busuanzi/>} {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && <Busuanzi/>}

View File

@@ -1,4 +1,5 @@
import CommonHead from '@/components/CommonHead' import CommonHead from '@/components/CommonHead'
import Link from 'next/link'
/** /**
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏 * 基础布局 采用左右两侧布局,移动端使用顶部导航栏
@@ -6,14 +7,31 @@ import CommonHead from '@/components/CommonHead'
* @returns {JSX.Element} * @returns {JSX.Element}
* @constructor * @constructor
*/ */
const LayoutBase = (props) => { const LayoutBase = props => {
const { children, meta } = props const { children, meta } = props
return <div> return (
<CommonHead meta={meta} /> <div>
<main id='wrapper' className='flex justify-center flex-1 pb-12'> <CommonHead meta={meta} />
{children} {/* 导航菜单 */}
</main> <div className="w-full flex justify-center my-2">
</div> <nav className="max-w-6xl space-x-3 underline">
<Link href="/">
<a>首页</a>
</Link>
<Link href="/category">
<a>分类</a>
</Link>
<Link href="/tag">
<a>标签</a>
</Link>
</nav>
</div>
{/* 内容主体 */}
<main id="wrapper" className="flex justify-center flex-1 pb-12">
<div className="max-w-6xl">{children}</div>
</main>
</div>
)
} }
export default LayoutBase export default LayoutBase

View File

@@ -1,6 +1,19 @@
import Link from 'next/link'
import LayoutBase from './LayoutBase' import LayoutBase from './LayoutBase'
export const LayoutIndex = (props) => { export const LayoutIndex = props => {
// const { posts, tags, meta, categories, postCount, latestPosts } = props const { posts } = props
return <LayoutBase {...props}>Index</LayoutBase> return (
<LayoutBase {...props}>
Index
{posts.map(p => (
<div key={p.id} className='border my-12'>
<Link href={`/article/${p.slug}`}>
<a className='underline cursor-pointer'>{p.title}</a>
</Link>
<div>{p.summary}</div>
</div>
))}
</LayoutBase>
)
} }

View File

@@ -6,14 +6,20 @@ import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-markup' import 'prismjs/components/prism-markup'
import 'prismjs/components/prism-python' import 'prismjs/components/prism-python'
import 'prismjs/components/prism-typescript' import 'prismjs/components/prism-typescript'
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x' import {
Code,
Collection,
CollectionRow,
Equation,
NotionRenderer
} from 'react-notion-x'
import LayoutBase from './LayoutBase' import LayoutBase from './LayoutBase'
const mapPageUrl = id => { const mapPageUrl = id => {
return 'https://www.notion.so/' + id.replace(/-/g, '') return 'https://www.notion.so/' + id.replace(/-/g, '')
} }
export const LayoutSlug = (props) => { export const LayoutSlug = props => {
const { post } = props const { post } = props
const meta = { const meta = {
title: `${post.title} | ${BLOG.TITLE}`, title: `${post.title} | ${BLOG.TITLE}`,
@@ -27,25 +33,27 @@ export const LayoutSlug = (props) => {
post.toc = getPageTableOfContents(post, post.blockMap) post.toc = getPageTableOfContents(post, post.blockMap)
} }
return <LayoutBase {...props} meta={meta}> return (
<h1>Slug - {post?.title}</h1> <LayoutBase {...props} meta={meta}>
<p> <div>
{/* Notion文章主体 */} <h2>{post?.title}</h2>
<section id='notion-article' className='px-1'> <p>
{post.blockMap && ( <section id="notion-article" className="px-1">
<NotionRenderer {post.blockMap && (
recordMap={post.blockMap} <NotionRenderer
mapPageUrl={mapPageUrl} recordMap={post.blockMap}
components={{ mapPageUrl={mapPageUrl}
equation: Equation, components={{
code: Code, equation: Equation,
collectionRow: CollectionRow, code: Code,
collection: Collection collectionRow: CollectionRow,
}} collection: Collection
/> }}
)} />
</section> )}
</p> </section>
</p>
</LayoutBase> </div>
</LayoutBase>
)
} }

View File

@@ -20,7 +20,7 @@ const SearchDrawer = ({ cRef, slot }) => {
}) })
return ( return (
<div id='search-drawer-wrapper' ref={searchDrawer} className='hidden'> <div id='search-drawer-wrapper' ref={searchDrawer} className='hidden'>
<div className='flex-col fixed px-5 w-full left-0 top-14 z-50 justify-center'> <div className='flex-col fixed px-5 w-full left-0 top-14 z-40 justify-center'>
<div className='md:max-w-3xl w-full mx-auto animate__animated animate__faster animate__fadeIn'> <div className='md:max-w-3xl w-full mx-auto animate__animated animate__faster animate__fadeIn'>
<SearchInput cRef={searchInputRef} /> <SearchInput cRef={searchInputRef} />
{slot} {slot}

View File

@@ -11,7 +11,7 @@ export default function TopNavBar (props) {
const { className, customNav } = props const { className, customNav } = props
const router = useRouter() const router = useRouter()
return <div id='top-nav' className={'sticky top-0 lg:relative w-full z-50 ' + className}> return <div id='top-nav' className={'sticky top-0 lg:relative w-full z-40 ' + className}>
<div className='flex w-full h-12 shadow bg-white dark:bg-gray-900 px-5 items-between'> <div className='flex w-full h-12 shadow bg-white dark:bg-gray-900 px-5 items-between'>
<LogoBar /> <LogoBar />

View File

@@ -20,7 +20,7 @@ const SearchDrawer = ({ cRef, slot }) => {
}) })
return ( return (
<div id='search-drawer-wrapper' ref={searchDrawer} className='hidden'> <div id='search-drawer-wrapper' ref={searchDrawer} className='hidden'>
<div className='flex-col fixed px-5 w-full left-0 top-14 z-50 justify-center'> <div className='flex-col fixed px-5 w-full left-0 top-14 z-40 justify-center'>
<div className='md:max-w-3xl w-full mx-auto animate__animated animate__faster animate__fadeIn'> <div className='md:max-w-3xl w-full mx-auto animate__animated animate__faster animate__fadeIn'>
<SearchInput cRef={searchInputRef} /> <SearchInput cRef={searchInputRef} />
{slot} {slot}

View File

@@ -58,7 +58,7 @@ const ShareBar = ({ post }) => {
<a className='text-green-600' ref={btnRef} onMouseEnter={openPopover} onMouseLeave={closePopover}> <a className='text-green-600' ref={btnRef} onMouseEnter={openPopover} onMouseLeave={closePopover}>
<i className='fab fa-weixin'/> <i className='fab fa-weixin'/>
<div ref={popoverRef} className={(qrCodeShow ? 'animate__animated animate__fadeIn ' : 'hidden') + ' text-center py-2'}> <div ref={popoverRef} className={(qrCodeShow ? 'animate__animated animate__fadeIn ' : 'hidden') + ' text-center py-2'}>
<div className='p-2 bg-white border-0 duration-200 transform block z-50 font-normal shadow-xl mr-10'> <div className='p-2 bg-white border-0 duration-200 transform block z-40 font-normal shadow-xl mr-10'>
<QRCode value={shareUrl} fgColor='#000000' /> <QRCode value={shareUrl} fgColor='#000000' />
</div> </div>
<span className='bg-white text-black font-semibold p-1 mb-0 rounded-t-lg text-sm mx-auto mr-10'> <span className='bg-white text-black font-semibold p-1 mb-0 rounded-t-lg text-sm mx-auto mr-10'>

View File

@@ -48,7 +48,7 @@ const SideBarDrawer = ({ post, cRef, tags, slot, categories, currentCategory })
} }
return <div id='sidebar-wrapper' className='hidden'> return <div id='sidebar-wrapper' className='hidden'>
<div id='sidebar-drawer' className='-ml-80 bg-white dark:bg-gray-900 flex flex-col duration-300 fixed h-full left-0 overflow-y-scroll scroll-hidden top-0 z-50'> <div id='sidebar-drawer' className='-ml-80 bg-white dark:bg-gray-900 flex flex-col duration-300 fixed h-full left-0 overflow-y-scroll scroll-hidden top-0 z-40'>
<SideBar tags={tags} post={post} slot={slot} categories={categories} currentCategory={currentCategory} /> <SideBar tags={tags} post={post} slot={slot} categories={categories} currentCategory={currentCategory} />
</div> </div>
{/* 背景蒙版 */} {/* 背景蒙版 */}