mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 23:16:47 +00:00
多语言配置,starter主题微调、兼容
This commit is contained in:
@@ -52,7 +52,7 @@ export const siteConfig = (key, defaultVal = null, extendConfig = null) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 其次 有传入的配置参考,则尝试读取
|
||||
// 其次 有传入的extendConfig,则尝试读取
|
||||
if (!val && extendConfig) {
|
||||
val = extendConfig[key]
|
||||
}
|
||||
@@ -64,24 +64,37 @@ export const siteConfig = (key, defaultVal = null, extendConfig = null) => {
|
||||
|
||||
if (!val) {
|
||||
return defaultVal
|
||||
} else {
|
||||
if (typeof val === 'string') {
|
||||
if (val === 'true' || val === 'false') {
|
||||
return JSON.parse(val)
|
||||
}
|
||||
if (/^\d+$/.test(val)) {
|
||||
// 如果是数字,使用parseFloat或者parseInt将字符串转换为数字
|
||||
return parseInt(val)
|
||||
}
|
||||
return val
|
||||
} else {
|
||||
try {
|
||||
return JSON.parse(val)
|
||||
} catch (error) {
|
||||
// 如果值是一个字符串但不是有效的 JSON 格式,直接返回字符串
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 从Notion_CONFIG读取的配置通常都是字符串,适当转义
|
||||
if (typeof val === 'string') {
|
||||
// 解析布尔
|
||||
if (val === 'true' || val === 'false') {
|
||||
return JSON.parse(val)
|
||||
}
|
||||
|
||||
// 解析数字,parseInt将字符串转换为数字
|
||||
if (/^\d+$/.test(val)) {
|
||||
return parseInt(val)
|
||||
}
|
||||
// 转移 [] , {} 这种json串为json对象
|
||||
try {
|
||||
const parsedJson = JSON.parse(val)
|
||||
// 检查解析后的结果是否是对象或数组
|
||||
if (typeof parsedJson === 'object' && parsedJson !== null) {
|
||||
return parsedJson
|
||||
}
|
||||
} catch (error) {
|
||||
// JSON 解析失败,返回原始字符串值
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(val)
|
||||
} catch (error) {
|
||||
// 如果值是一个字符串但不是有效的 JSON 格式,直接返回字符串
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*
|
||||
*/
|
||||
import { getDateValue, getTextContent } from 'notion-utils'
|
||||
import { deepClone } from '../utils'
|
||||
import getAllPageIds from './getAllPageIds'
|
||||
import { getPostBlocks } from './getPostBlocks'
|
||||
|
||||
@@ -162,9 +163,12 @@ export async function getConfigMapFromConfigPage(allPages) {
|
||||
}
|
||||
|
||||
// 最后检查Notion_Config页面的INLINE_CONFIG,是否是一个js对象
|
||||
const inlineConfigs = parseConfig(configPage?.INLINE_CONFIG)
|
||||
|
||||
return Object.assign({}, notionConfig, inlineConfigs)
|
||||
const combine = Object.assign(
|
||||
{},
|
||||
deepClone(notionConfig),
|
||||
parseConfig(notionConfig?.INLINE_CONFIG)
|
||||
)
|
||||
return combine
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,19 +180,13 @@ export function parseConfig(configString) {
|
||||
if (!configString) {
|
||||
return {}
|
||||
}
|
||||
// 解析对象
|
||||
try {
|
||||
// 尝试解析为 JSON 对象
|
||||
const jsonConfig = JSON.parse(configString)
|
||||
return jsonConfig
|
||||
} catch (error) {
|
||||
// 如果解析失败,则尝试使用 eval()
|
||||
try {
|
||||
// eslint-disable-next-line no-eval
|
||||
const config = eval('(' + configString + ')')
|
||||
return config
|
||||
} catch (evalError) {
|
||||
console.error('解析 INLINE_CONFIG 配置时出错:', evalError)
|
||||
return {}
|
||||
}
|
||||
// eslint-disable-next-line no-eval
|
||||
const config = eval('(' + configString + ')')
|
||||
return config
|
||||
} catch (evalError) {
|
||||
console.error('解析 eval(INLINE_CONFIG) 配置时出错:', evalError)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,13 +55,14 @@ export async function getStaticProps({
|
||||
locale
|
||||
}) {
|
||||
let fullSlug = prefix + '/' + slug + '/' + suffix.join('/')
|
||||
if (JSON.parse(BLOG.PSEUDO_STATIC)) {
|
||||
const from = `slug-props-${fullSlug}`
|
||||
const props = await getGlobalData({ from, locale })
|
||||
if (siteConfig('PSEUDO_STATIC', BLOG.PSEUDO_STATIC, props.NOTION_CONFIG)) {
|
||||
if (!fullSlug.endsWith('.html')) {
|
||||
fullSlug += '.html'
|
||||
}
|
||||
}
|
||||
const from = `slug-props-${fullSlug}`
|
||||
const props = await getGlobalData({ from, locale })
|
||||
|
||||
// 在列表内查找文章
|
||||
props.post = props?.allPages?.find(p => {
|
||||
return (
|
||||
|
||||
@@ -39,13 +39,14 @@ export async function getStaticPaths() {
|
||||
|
||||
export async function getStaticProps({ params: { prefix, slug }, locale }) {
|
||||
let fullSlug = prefix + '/' + slug
|
||||
if (JSON.parse(BLOG.PSEUDO_STATIC)) {
|
||||
const from = `slug-props-${fullSlug}`
|
||||
const props = await getGlobalData({ from, locale })
|
||||
|
||||
if (siteConfig('PSEUDO_STATIC', BLOG.PSEUDO_STATIC, props.NOTION_CONFIG)) {
|
||||
if (!fullSlug.endsWith('.html')) {
|
||||
fullSlug += '.html'
|
||||
}
|
||||
}
|
||||
const from = `slug-props-${fullSlug}`
|
||||
const props = await getGlobalData({ from, locale })
|
||||
// 在列表内查找文章
|
||||
props.post = props?.allPages?.find(p => {
|
||||
return (
|
||||
|
||||
@@ -81,13 +81,14 @@ export async function getStaticPaths() {
|
||||
|
||||
export async function getStaticProps({ params: { prefix }, locale }) {
|
||||
let fullSlug = prefix
|
||||
if (JSON.parse(BLOG.PSEUDO_STATIC)) {
|
||||
const from = `slug-props-${fullSlug}`
|
||||
const props = await getGlobalData({ from, locale })
|
||||
if (siteConfig('PSEUDO_STATIC', BLOG.PSEUDO_STATIC, props.NOTION_CONFIG)) {
|
||||
if (!fullSlug.endsWith('.html')) {
|
||||
fullSlug += '.html'
|
||||
}
|
||||
}
|
||||
const from = `slug-props-${fullSlug}`
|
||||
const props = await getGlobalData({ from, locale })
|
||||
|
||||
// 在列表内查找文章
|
||||
props.post = props?.allPages?.find(p => {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// eslint-disable-next-line @next/next/no-document-import-in-page
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
import BLOG from '@/blog.config'
|
||||
import Document, { Head, Html, Main, NextScript } from 'next/document'
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx) {
|
||||
@@ -10,29 +10,52 @@ class MyDocument extends Document {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang={BLOG.LANG}>
|
||||
<Head>
|
||||
<link rel='icon' href= {`${BLOG.BLOG_FAVICON}`} />
|
||||
{/* 预加载字体 */}
|
||||
{BLOG.FONT_AWESOME && <>
|
||||
<link rel='preload' href={BLOG.FONT_AWESOME} as="style" crossOrigin="anonymous" />
|
||||
<link rel="stylesheet" href={BLOG.FONT_AWESOME} crossOrigin="anonymous" referrerPolicy="no-referrer" />
|
||||
</>}
|
||||
<Html lang={BLOG.LANG}>
|
||||
<Head>
|
||||
<link rel='icon' href={`${BLOG.BLOG_FAVICON}`} />
|
||||
{/* 预加载字体 */}
|
||||
{BLOG.FONT_AWESOME && (
|
||||
<>
|
||||
<link
|
||||
rel='preload'
|
||||
href={BLOG.FONT_AWESOME}
|
||||
as='style'
|
||||
crossOrigin='anonymous'
|
||||
/>
|
||||
<link
|
||||
rel='stylesheet'
|
||||
href={BLOG.FONT_AWESOME}
|
||||
crossOrigin='anonymous'
|
||||
referrerPolicy='no-referrer'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{BLOG.FONT_URL?.map((fontUrl, index) => {
|
||||
if (fontUrl.endsWith('.css') || fontUrl.includes('googleapis.com/css')) {
|
||||
return <link key={index} rel="stylesheet" href={fontUrl} />
|
||||
} else {
|
||||
return <link key={index} rel="preload" href={fontUrl} as="font" type="font/woff2" />
|
||||
}
|
||||
})}
|
||||
</Head>
|
||||
{BLOG.FONT_URL?.map((fontUrl, index) => {
|
||||
if (
|
||||
fontUrl.endsWith('.css') ||
|
||||
fontUrl.includes('googleapis.com/css')
|
||||
) {
|
||||
return <link key={index} rel='stylesheet' href={fontUrl} />
|
||||
} else {
|
||||
return (
|
||||
<link
|
||||
key={index}
|
||||
rel='preload'
|
||||
href={fontUrl}
|
||||
as='font'
|
||||
type='font/woff2'
|
||||
/>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</Head>
|
||||
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +1,187 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import SocialButton from '@/themes/fukasawa/components/SocialButton'
|
||||
import CONFIG from '../config'
|
||||
import { Logo } from './Logo'
|
||||
import SocialButton from '@/themes/fukasawa/components/SocialButton'
|
||||
import { SVGFooterCircleBG } from './svg/SVGFooterCircleBG'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
export const Footer = (props) => {
|
||||
export const Footer = props => {
|
||||
const latestPosts = props?.latestPosts ? props?.latestPosts.slice(0, 2) : []
|
||||
|
||||
return <>
|
||||
{/* <!-- ====== Footer Section Start --> */}
|
||||
<footer
|
||||
className="wow fadeInUp relative z-10 bg-[#090E34] pt-20 lg:pt-[100px]"
|
||||
data-wow-delay=".15s"
|
||||
>
|
||||
<div className="container">
|
||||
<div className="-mx-4 flex flex-wrap">
|
||||
<div className="w-full px-4 sm:w-1/2 md:w-1/2 lg:w-4/12 xl:w-3/12">
|
||||
<div className="mb-10 w-full">
|
||||
<a
|
||||
className="-mx-4 mb-6 inline-block max-w-[160px]"
|
||||
>
|
||||
<Logo white={true}/>
|
||||
</a>
|
||||
<p className="mb-8 max-w-[270px] text-base text-gray-7">
|
||||
{siteConfig('STARTER_FOOTER_SLOGAN', null, CONFIG)}
|
||||
</p>
|
||||
<div className="-mx-3 flex items-center">
|
||||
<div className='mx-3'><SocialButton/></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 中间三列菜单组 */}
|
||||
{CONFIG.STARTER_FOOTER_LINK_GROUP?.map((item, index) => {
|
||||
return <div key={index} className="w-full px-4 sm:w-1/2 md:w-1/2 lg:w-2/12 xl:w-2/12">
|
||||
<div className="mb-10 w-full">
|
||||
<h4 className="mb-9 text-lg font-semibold text-white">
|
||||
{item.TITLE}
|
||||
</h4>
|
||||
<ul>
|
||||
{item?.LINK_GROUP?.map((l, i) => {
|
||||
return <li key={i}>
|
||||
<a href={l.URL}
|
||||
className="mb-3 inline-block text-base text-gray-7 hover:text-primary"
|
||||
>
|
||||
{l.TITLE}
|
||||
</a>
|
||||
</li>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
})}
|
||||
|
||||
{/* 页脚右侧最新博文 */}
|
||||
<div className="w-full px-4 md:w-2/3 lg:w-6/12 xl:w-3/12">
|
||||
<div className="mb-10 w-full">
|
||||
<h4 className="mb-9 text-lg font-semibold text-white">
|
||||
{siteConfig('STARTER_FOOTER_BLOG_LATEST_TITLE', null, CONFIG)}
|
||||
</h4>
|
||||
{/* 展示两条最新博客文章 */}
|
||||
<div className="flex flex-col gap-8">
|
||||
|
||||
{latestPosts?.map((item, index) => {
|
||||
const url = checkContainHttp(item.slug) ? sliceUrlFromHttp(item.slug) : `${siteConfig('SUB_PATH', '')}/${item.slug}`
|
||||
|
||||
return <a key={index}
|
||||
href={url}
|
||||
className="group flex items-center gap-[22px]"
|
||||
>
|
||||
<div className="overflow-hidden rounded w-20 h-12">
|
||||
<img
|
||||
src={item.pageCoverThumbnail}
|
||||
alt={item.title}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className="line-clamp-2 max-w-[180px] text-base text-gray-7 group-hover:text-white"
|
||||
>
|
||||
{item.title}
|
||||
</span>
|
||||
const STARTER_FOOTER_LINK_GROUP = siteConfig(
|
||||
'STARTER_FOOTER_LINK_GROUP',
|
||||
[],
|
||||
CONFIG
|
||||
)
|
||||
return (
|
||||
<>
|
||||
{/* <!-- ====== Footer Section Start --> */}
|
||||
<footer
|
||||
className='wow fadeInUp relative z-10 bg-[#090E34] pt-20 lg:pt-[100px]'
|
||||
data-wow-delay='.15s'>
|
||||
<div className='container'>
|
||||
<div className='-mx-4 flex flex-wrap'>
|
||||
<div className='w-full px-4 sm:w-1/2 md:w-1/2 lg:w-4/12 xl:w-3/12'>
|
||||
<div className='mb-10 w-full'>
|
||||
<a className='-mx-4 mb-6 inline-block max-w-[160px]'>
|
||||
<Logo white={true} />
|
||||
</a>
|
||||
})}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 底部版权信息相关 */}
|
||||
|
||||
<div
|
||||
className="mt-12 border-t border-[#8890A4] border-opacity-40 py-8 lg:mt-[60px]"
|
||||
>
|
||||
<div className="container">
|
||||
<div className="-mx-4 flex flex-wrap">
|
||||
<div className="w-full px-4 md:w-2/3 lg:w-1/2">
|
||||
<div className="my-1">
|
||||
<div
|
||||
className="-mx-3 flex items-center justify-center md:justify-start"
|
||||
>
|
||||
<a
|
||||
href= {siteConfig('STARTER_FOOTER_PRIVACY_POLICY_URL', null, CONFIG)}
|
||||
className="px-3 text-base text-gray-7 hover:text-white hover:underline"
|
||||
>
|
||||
{siteConfig('STARTER_FOOTER_PRIVACY_POLICY_TEXT', null, CONFIG)}
|
||||
</a>
|
||||
<a
|
||||
href= {siteConfig('STARTER_FOOTER_PRIVACY_LEGAL_NOTICE_URL', null, CONFIG)}
|
||||
className="px-3 text-base text-gray-7 hover:text-white hover:underline"
|
||||
>
|
||||
{siteConfig('STARTER_FOOTER_PRIVACY_LEGAL_NOTICE_TEXT', null, CONFIG)}
|
||||
</a>
|
||||
<a
|
||||
href= {siteConfig('STARTER_FOOTER_PRIVACY_TERMS_OF_SERVICE_URL', null, CONFIG)}
|
||||
className="px-3 text-base text-gray-7 hover:text-white hover:underline"
|
||||
>
|
||||
{siteConfig('STARTER_FOOTER_PRIVACY_TERMS_OF_SERVICE_TEXT', null, CONFIG)}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full px-4 md:w-1/3 lg:w-1/2">
|
||||
<div className="my-1 flex justify-center md:justify-end">
|
||||
<p className="text-base text-gray-7">
|
||||
Designed and Developed by
|
||||
<a
|
||||
href="https://github.com/tangly1024/NotionNext"
|
||||
rel="nofollow noopner noreferrer"
|
||||
target="_blank"
|
||||
className="px-1 text-gray-1 hover:underline"
|
||||
>
|
||||
NotionNext {siteConfig('VERSION')}
|
||||
</a>
|
||||
<p className='mb-8 max-w-[270px] text-base text-gray-7'>
|
||||
{siteConfig('STARTER_FOOTER_SLOGAN', null, CONFIG)}
|
||||
</p>
|
||||
<div className='-mx-3 flex items-center'>
|
||||
<div className='mx-3'>
|
||||
<SocialButton />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 中间三列菜单组 */}
|
||||
{STARTER_FOOTER_LINK_GROUP?.map((item, index) => {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className='w-full px-4 sm:w-1/2 md:w-1/2 lg:w-2/12 xl:w-2/12'>
|
||||
<div className='mb-10 w-full'>
|
||||
<h4 className='mb-9 text-lg font-semibold text-white'>
|
||||
{item.TITLE}
|
||||
</h4>
|
||||
<ul>
|
||||
{item?.LINK_GROUP?.map((l, i) => {
|
||||
return (
|
||||
<li key={i}>
|
||||
<a
|
||||
href={l.URL}
|
||||
className='mb-3 inline-block text-base text-gray-7 hover:text-primary'>
|
||||
{l.TITLE}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
{/* 页脚右侧最新博文 */}
|
||||
<div className='w-full px-4 md:w-2/3 lg:w-6/12 xl:w-3/12'>
|
||||
<div className='mb-10 w-full'>
|
||||
<h4 className='mb-9 text-lg font-semibold text-white'>
|
||||
{siteConfig('STARTER_FOOTER_BLOG_LATEST_TITLE', null, CONFIG)}
|
||||
</h4>
|
||||
{/* 展示两条最新博客文章 */}
|
||||
<div className='flex flex-col gap-8'>
|
||||
{latestPosts?.map((item, index) => {
|
||||
const url = checkContainHttp(item.slug)
|
||||
? sliceUrlFromHttp(item.slug)
|
||||
: `${siteConfig('SUB_PATH', '')}/${item.slug}`
|
||||
|
||||
return (
|
||||
<a
|
||||
key={index}
|
||||
href={url}
|
||||
className='group flex items-center gap-[22px]'>
|
||||
<div className='overflow-hidden rounded w-20 h-12'>
|
||||
<img src={item.pageCoverThumbnail} alt={item.title} />
|
||||
</div>
|
||||
<span className='line-clamp-2 max-w-[180px] text-base text-gray-7 group-hover:text-white'>
|
||||
{item.title}
|
||||
</span>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer 背景 */}
|
||||
<div>
|
||||
<span className="absolute left-0 top-0 z-[-1]">
|
||||
<img src="/images/starter/footer/shape-1.svg" alt="" />
|
||||
</span>
|
||||
{/* 底部版权信息相关 */}
|
||||
|
||||
<span className="absolute bottom-0 right-0 z-[-1]">
|
||||
<img src="/images/starter/footer/shape-3.svg" alt="" />
|
||||
</span>
|
||||
<div className='mt-12 border-t border-[#8890A4] border-opacity-40 py-8 lg:mt-[60px]'>
|
||||
<div className='container'>
|
||||
<div className='-mx-4 flex flex-wrap'>
|
||||
<div className='w-full px-4 md:w-2/3 lg:w-1/2'>
|
||||
<div className='my-1'>
|
||||
<div className='-mx-3 flex items-center justify-center md:justify-start'>
|
||||
<a
|
||||
href={siteConfig(
|
||||
'STARTER_FOOTER_PRIVACY_POLICY_URL',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
className='px-3 text-base text-gray-7 hover:text-white hover:underline'>
|
||||
{siteConfig(
|
||||
'STARTER_FOOTER_PRIVACY_POLICY_TEXT',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
</a>
|
||||
<a
|
||||
href={siteConfig(
|
||||
'STARTER_FOOTER_PRIVACY_LEGAL_NOTICE_URL',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
className='px-3 text-base text-gray-7 hover:text-white hover:underline'>
|
||||
{siteConfig(
|
||||
'STARTER_FOOTER_PRIVACY_LEGAL_NOTICE_TEXT',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
</a>
|
||||
<a
|
||||
href={siteConfig(
|
||||
'STARTER_FOOTER_PRIVACY_TERMS_OF_SERVICE_URL',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
className='px-3 text-base text-gray-7 hover:text-white hover:underline'>
|
||||
{siteConfig(
|
||||
'STARTER_FOOTER_PRIVACY_TERMS_OF_SERVICE_TEXT',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='w-full px-4 md:w-1/3 lg:w-1/2'>
|
||||
<div className='my-1 flex justify-center md:justify-end'>
|
||||
<p className='text-base text-gray-7'>
|
||||
Designed and Developed by
|
||||
<a
|
||||
href='https://github.com/tangly1024/NotionNext'
|
||||
rel='nofollow noopner noreferrer'
|
||||
target='_blank'
|
||||
className='px-1 text-gray-1 hover:underline'>
|
||||
NotionNext {siteConfig('VERSION')}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span className="absolute right-0 top-0 z-[-1]">
|
||||
<SVGFooterCircleBG/>
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
{/* <!-- ====== Footer Section End --> */}
|
||||
{/* Footer 背景 */}
|
||||
<div>
|
||||
<span className='absolute left-0 top-0 z-[-1]'>
|
||||
<img src='/images/starter/footer/shape-1.svg' alt='' />
|
||||
</span>
|
||||
|
||||
<span className='absolute bottom-0 right-0 z-[-1]'>
|
||||
<img src='/images/starter/footer/shape-3.svg' alt='' />
|
||||
</span>
|
||||
|
||||
<span className='absolute right-0 top-0 z-[-1]'>
|
||||
<SVGFooterCircleBG />
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
{/* <!-- ====== Footer Section End --> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,94 +2,85 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import CONFIG from '../config'
|
||||
import { SVGAvatarBG } from './svg/SVGAvatarBG'
|
||||
import { SVGFacebook } from './svg/SVGFacebook'
|
||||
import { SVGTwitter } from './svg/SVGTwitter'
|
||||
import { SVGInstagram } from './svg/SVGInstagram'
|
||||
|
||||
export const Team = () => {
|
||||
return <>
|
||||
{/* <!-- ====== Team Section Start --> */}
|
||||
<section
|
||||
id="team"
|
||||
className="overflow-hidden bg-gray-1 pb-12 pt-20 dark:bg-dark-2 lg:pb-[90px] lg:pt-[120px]"
|
||||
>
|
||||
<div className="container mx-auto">
|
||||
<div className="-mx-4 flex flex-wrap">
|
||||
<div className="w-full px-4">
|
||||
<div className="mx-auto mb-[60px] max-w-[485px] text-center">
|
||||
<span className="mb-2 block text-lg font-semibold text-primary">
|
||||
{siteConfig('STARTER_TEAM_TITLE', null, CONFIG)}
|
||||
</span>
|
||||
<h2
|
||||
className="mb-3 text-3xl font-bold leading-[1.2] text-dark dark:text-white sm:text-4xl md:text-[40px]"
|
||||
>
|
||||
{siteConfig('STARTER_TEAM_TEXT_1', null, CONFIG)}
|
||||
</h2>
|
||||
<p dangerouslySetInnerHTML={
|
||||
{ __html: siteConfig('STARTER_TEAM_TEXT_2', null, CONFIG) }
|
||||
} className="text-base text-body-color dark:text-dark-6">
|
||||
</p>
|
||||
return (
|
||||
<>
|
||||
{/* <!-- ====== Team Section Start --> */}
|
||||
<section
|
||||
id='team'
|
||||
className='overflow-hidden bg-gray-1 pb-12 pt-20 dark:bg-dark-2 lg:pb-[90px] lg:pt-[120px]'>
|
||||
<div className='container mx-auto'>
|
||||
<div className='-mx-4 flex flex-wrap'>
|
||||
<div className='w-full px-4'>
|
||||
<div className='mx-auto mb-[60px] max-w-[485px] text-center'>
|
||||
<span className='mb-2 block text-lg font-semibold text-primary'>
|
||||
{siteConfig('STARTER_TEAM_TITLE', null, CONFIG)}
|
||||
</span>
|
||||
<h2 className='mb-3 text-3xl font-bold leading-[1.2] text-dark dark:text-white sm:text-4xl md:text-[40px]'>
|
||||
{siteConfig('STARTER_TEAM_TEXT_1', null, CONFIG)}
|
||||
</h2>
|
||||
<p
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: siteConfig('STARTER_TEAM_TEXT_2', null, CONFIG)
|
||||
}}
|
||||
className='text-base text-body-color dark:text-dark-6'></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 团队成员排列矩阵 */}
|
||||
<div className="-mx-4 flex flex-wrap justify-center">
|
||||
{/* 团队成员排列矩阵 */}
|
||||
<div className='-mx-4 flex flex-wrap justify-center'>
|
||||
{CONFIG.STARTER_TEAM_ITEMS.map((item, index) => {
|
||||
return <div key={index} className="w-full px-4 sm:w-1/2 lg:w-1/4 xl:w-1/4">
|
||||
return (
|
||||
<div
|
||||
className="group mb-8 rounded-xl bg-white px-5 pb-10 pt-12 shadow-testimonial dark:bg-dark dark:shadow-none"
|
||||
>
|
||||
{/* 头像 */}
|
||||
<div className="relative z-10 mx-auto mb-5 h-[120px] w-[120px]">
|
||||
<img
|
||||
src={item.STARTER_TEAM_ITEM_AVATAR}
|
||||
alt="team image"
|
||||
className="h-[120px] w-[120px] rounded-full"
|
||||
/>
|
||||
<span
|
||||
className="absolute bottom-0 left-0 -z-10 h-10 w-10 rounded-full bg-secondary opacity-0 transition-all group-hover:opacity-100"
|
||||
></span>
|
||||
<span
|
||||
className="absolute right-0 top-0 -z-10 opacity-0 transition-all group-hover:opacity-100"
|
||||
>
|
||||
<SVGAvatarBG/>
|
||||
</span>
|
||||
</div>
|
||||
key={index}
|
||||
className='w-full px-4 sm:w-1/2 lg:w-1/4 xl:w-1/4'>
|
||||
<div className='group mb-8 rounded-xl bg-white px-5 pb-10 pt-12 shadow-testimonial dark:bg-dark dark:shadow-none'>
|
||||
{/* 头像 */}
|
||||
<div className='relative z-10 mx-auto mb-5 h-[120px] w-[120px]'>
|
||||
<img
|
||||
src={item.STARTER_TEAM_ITEM_AVATAR}
|
||||
alt='team image'
|
||||
className='h-[120px] w-[120px] rounded-full'
|
||||
/>
|
||||
<span className='absolute bottom-0 left-0 -z-10 h-10 w-10 rounded-full bg-secondary opacity-0 transition-all group-hover:opacity-100'></span>
|
||||
<span className='absolute right-0 top-0 -z-10 opacity-0 transition-all group-hover:opacity-100'>
|
||||
<SVGAvatarBG />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* 文字介绍 */}
|
||||
<div className="text-center">
|
||||
{/* 文字介绍 */}
|
||||
<div className='text-center'>
|
||||
<h4 className='mb-1 text-lg font-semibold text-dark dark:text-white'>
|
||||
{item.STARTER_TEAM_ITEM_NICKNAME}
|
||||
</h4>
|
||||
|
||||
<h4
|
||||
className="mb-1 text-lg font-semibold text-dark dark:text-white"
|
||||
>
|
||||
{item.STARTER_TEAM_ITEM_NICKNAME}
|
||||
</h4>
|
||||
<p className='mb-5 text-sm text-body-color dark:text-dark-6'>
|
||||
{item.STARTER_TEAM_ITEM_DESCRIPTION}
|
||||
</p>
|
||||
|
||||
<p className="mb-5 text-sm text-body-color dark:text-dark-6">
|
||||
{item.STARTER_TEAM_ITEM_DESCRIPTION}
|
||||
</p>
|
||||
|
||||
{/* 社交链接 */}
|
||||
<div className="flex items-center justify-center gap-5">
|
||||
<a className="text-dark-6 hover:text-primary" >
|
||||
<SVGFacebook/>
|
||||
</a>
|
||||
<a className="text-dark-6 hover:text-primary" >
|
||||
<SVGTwitter/>
|
||||
</a>
|
||||
<a className="text-dark-6 hover:text-primary" >
|
||||
<SVGInstagram/>
|
||||
</a>
|
||||
{/* 社交链接 */}
|
||||
{/* <div className='flex items-center justify-center gap-5'>
|
||||
<a className='text-dark-6 hover:text-primary'>
|
||||
<SVGFacebook className='fill-current' />
|
||||
</a>
|
||||
<a className='text-dark-6 hover:text-primary'>
|
||||
<SVGTwitter className='fill-current' />
|
||||
</a>
|
||||
<a className='text-dark-6 hover:text-primary'>
|
||||
<SVGInstagram className='fill-current' />
|
||||
</a>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/* <!-- ====== Team Section End --> */}
|
||||
</section>
|
||||
{/* <!-- ====== Team Section End --> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
/* eslint-disable react/no-unescaped-entities */
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
|
||||
import { siteConfig } from '@/lib/config';
|
||||
import { loadExternalResource } from '@/lib/utils';
|
||||
import { useEffect } from 'react';
|
||||
import CONFIG from '../config';
|
||||
import { SVGLeftArrow } from './svg/SVGLeftArrow';
|
||||
import { SVGRightArrow } from './svg/SVGRightArrow';
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { loadExternalResource } from '@/lib/utils'
|
||||
import { useEffect } from 'react'
|
||||
import CONFIG from '../config'
|
||||
import { SVGLeftArrow } from './svg/SVGLeftArrow'
|
||||
import { SVGRightArrow } from './svg/SVGRightArrow'
|
||||
|
||||
/**
|
||||
* 一些外部js
|
||||
*/
|
||||
const loadExternal = async () => {
|
||||
await loadExternalResource('https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.css', 'css');
|
||||
await loadExternalResource('https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.js', 'js');
|
||||
await loadExternalResource(
|
||||
'https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.css',
|
||||
'css'
|
||||
)
|
||||
await loadExternalResource(
|
||||
'https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.js',
|
||||
'js'
|
||||
)
|
||||
|
||||
const Swiper = window.Swiper
|
||||
if (!Swiper) {
|
||||
@@ -45,101 +51,109 @@ const loadExternal = async () => {
|
||||
spaceBetween: 30
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
export const Testimonials = () => {
|
||||
useEffect(() => {
|
||||
loadExternal()
|
||||
}, [])
|
||||
// 用户评分
|
||||
const ratings = [1, 2, 3, 4, 5];
|
||||
return <>
|
||||
{/* <!-- ====== Testimonial Section Start --> */}
|
||||
<section
|
||||
id="testimonials"
|
||||
className="overflow-hidden bg-gray-1 py-20 dark:bg-dark-2 md:py-[120px]"
|
||||
>
|
||||
<div className="container mx-auto">
|
||||
<div className="-mx-4 flex flex-wrap justify-center">
|
||||
<div className="w-full px-4">
|
||||
<div className="mx-auto mb-[60px] max-w-[485px] text-center">
|
||||
<span className="mb-2 block text-lg font-semibold text-primary">
|
||||
{siteConfig('STARTER_TESTIMONIALS_TITLE', null, CONFIG)}
|
||||
</span>
|
||||
<h2
|
||||
className="mb-3 text-3xl font-bold leading-[1.2] text-dark dark:text-white sm:text-4xl md:text-[40px]"
|
||||
>
|
||||
{siteConfig('STARTER_TESTIMONIALS_TEXT_1', null, CONFIG)}
|
||||
</h2>
|
||||
<p className="text-base text-body-color dark:text-dark-6">
|
||||
{siteConfig('STARTER_TESTIMONIALS_TEXT_2', null, CONFIG)}
|
||||
</p>
|
||||
const ratings = [1, 2, 3, 4, 5]
|
||||
const STARTER_TESTIMONIALS_ITEMS = siteConfig(
|
||||
'STARTER_TESTIMONIALS_ITEMS',
|
||||
[],
|
||||
CONFIG
|
||||
)
|
||||
return (
|
||||
<>
|
||||
{/* <!-- ====== Testimonial Section Start --> */}
|
||||
<section
|
||||
id='testimonials'
|
||||
className='overflow-hidden bg-gray-1 py-20 dark:bg-dark-2 md:py-[120px]'>
|
||||
<div className='container mx-auto'>
|
||||
<div className='-mx-4 flex flex-wrap justify-center'>
|
||||
<div className='w-full px-4'>
|
||||
<div className='mx-auto mb-[60px] max-w-[485px] text-center'>
|
||||
<span className='mb-2 block text-lg font-semibold text-primary'>
|
||||
{siteConfig('STARTER_TESTIMONIALS_TITLE', null, CONFIG)}
|
||||
</span>
|
||||
<h2 className='mb-3 text-3xl font-bold leading-[1.2] text-dark dark:text-white sm:text-4xl md:text-[40px]'>
|
||||
{siteConfig('STARTER_TESTIMONIALS_TEXT_1', null, CONFIG)}
|
||||
</h2>
|
||||
<p className='text-base text-body-color dark:text-dark-6'>
|
||||
{siteConfig('STARTER_TESTIMONIALS_TEXT_2', null, CONFIG)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="-m-5">
|
||||
<div className="swiper testimonial-carousel common-carousel p-5">
|
||||
<div className="swiper-wrapper">
|
||||
|
||||
{/* 用户评价卡牌 */}
|
||||
{CONFIG.STARTER_TESTIMONIALS_ITEMS.map((item, index) => {
|
||||
return <div key={index} className="swiper-slide">
|
||||
<div
|
||||
className="rounded-xl bg-white px-4 py-[30px] shadow-testimonial dark:bg-dark sm:px-[30px]"
|
||||
>
|
||||
<div className="mb-[18px] flex items-center gap-[2px]">
|
||||
{ratings.map((rating, index) => (
|
||||
<img key={index} alt="star icon"// 为每个图片设置唯一的 key 属性
|
||||
src={siteConfig('STARTER_TESTIMONIALS_STAR_ICON', null, CONFIG)}/>
|
||||
))}
|
||||
<div className='-m-5'>
|
||||
<div className='swiper testimonial-carousel common-carousel p-5'>
|
||||
<div className='swiper-wrapper'>
|
||||
{/* 用户评价卡牌 */}
|
||||
{STARTER_TESTIMONIALS_ITEMS.map((item, index) => {
|
||||
return (
|
||||
<div key={index} className='swiper-slide'>
|
||||
<div className='rounded-xl bg-white px-4 py-[30px] shadow-testimonial dark:bg-dark sm:px-[30px]'>
|
||||
<div className='mb-[18px] flex items-center gap-[2px]'>
|
||||
{ratings.map((rating, index) => (
|
||||
<img
|
||||
key={index}
|
||||
alt='star icon' // 为每个图片设置唯一的 key 属性
|
||||
src={siteConfig(
|
||||
'STARTER_TESTIMONIALS_STAR_ICON',
|
||||
null,
|
||||
CONFIG
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="mb-6 text-base text-body-color dark:text-dark-6">
|
||||
“{item.STARTER_TESTIMONIALS_ITEM_TEXT}”
|
||||
<p className='mb-6 text-base text-body-color dark:text-dark-6'>
|
||||
“{item.STARTER_TESTIMONIALS_ITEM_TEXT}”
|
||||
</p>
|
||||
|
||||
<a href={item.STARTER_TESTIMONIALS_ITEM_URL} className="flex items-center gap-4">
|
||||
<div className="h-[50px] w-[50px] overflow-hidden rounded-full">
|
||||
<img
|
||||
src={item.STARTER_TESTIMONIALS_ITEM_AVATAR}
|
||||
alt="author"
|
||||
className="h-[50px] w-[50px] overflow-hidden rounded-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<a
|
||||
href={item.STARTER_TESTIMONIALS_ITEM_URL}
|
||||
className='flex items-center gap-4'>
|
||||
<div className='h-[50px] w-[50px] overflow-hidden rounded-full'>
|
||||
<img
|
||||
src={item.STARTER_TESTIMONIALS_ITEM_AVATAR}
|
||||
alt='author'
|
||||
className='h-[50px] w-[50px] overflow-hidden rounded-full object-cover'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3
|
||||
className="text-sm font-semibold text-dark dark:text-white"
|
||||
>
|
||||
{item.STARTER_TESTIMONIALS_ITEM_NICKNAME}
|
||||
</h3>
|
||||
<p className="text-xs text-body-secondary">
|
||||
{item.STARTER_TESTIMONIALS_ITEM_DESCRIPTION}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className='text-sm font-semibold text-dark dark:text-white'>
|
||||
{item.STARTER_TESTIMONIALS_ITEM_NICKNAME}
|
||||
</h3>
|
||||
<p className='text-xs text-body-secondary'>
|
||||
{item.STARTER_TESTIMONIALS_ITEM_DESCRIPTION}
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 切换按钮 */}
|
||||
<div className='mt-[60px] flex items-center justify-center gap-1'>
|
||||
<div className='swiper-button-prev'>
|
||||
<SVGLeftArrow />
|
||||
</div>
|
||||
<div className='swiper-button-next'>
|
||||
<SVGRightArrow />
|
||||
</div>
|
||||
})}
|
||||
|
||||
</div>
|
||||
|
||||
{/* 切换按钮 */}
|
||||
<div className="mt-[60px] flex items-center justify-center gap-1">
|
||||
<div className="swiper-button-prev">
|
||||
<SVGLeftArrow/>
|
||||
</div>
|
||||
<div className="swiper-button-next">
|
||||
<SVGRightArrow/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/* <!-- ====== Testimonial Section End --> */}
|
||||
</section>
|
||||
{/* <!-- ====== Testimonial Section End --> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,34 +9,35 @@
|
||||
* 2. 内容大部分是在此文件中写死,notion数据从props参数中传进来
|
||||
* 3. 您可在此网站找到更多喜欢的组件 https://www.tailwind-kit.com/
|
||||
*/
|
||||
import { useRouter } from 'next/router'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import CONFIG from './config'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import Loading from '@/components/Loading'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import { Style } from './style'
|
||||
import { NavBar } from './components/NavBar'
|
||||
import { Hero } from './components/Hero'
|
||||
import { Features } from './components/Features'
|
||||
import { About } from './components/About'
|
||||
import { Pricing } from './components/Pricing'
|
||||
import { Testimonials } from './components/Testimonials'
|
||||
import { FAQ } from './components/FAQ'
|
||||
import { Team } from './components/Team'
|
||||
import { Blog } from './components/Blog'
|
||||
import { Contact } from './components/Contact'
|
||||
import { Brand } from './components/Brand'
|
||||
import { Footer } from './components/Footer'
|
||||
import { BackToTopButton } from './components/BackToTopButton'
|
||||
import { Blog } from './components/Blog'
|
||||
import { Brand } from './components/Brand'
|
||||
import { Contact } from './components/Contact'
|
||||
import { FAQ } from './components/FAQ'
|
||||
import { Features } from './components/Features'
|
||||
import { Footer } from './components/Footer'
|
||||
import { Hero } from './components/Hero'
|
||||
import { NavBar } from './components/NavBar'
|
||||
import { Pricing } from './components/Pricing'
|
||||
import { Team } from './components/Team'
|
||||
import { Testimonials } from './components/Testimonials'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
// import { MadeWithButton } from './components/MadeWithButton'
|
||||
import { SVG404 } from './components/svg/SVG404'
|
||||
import BLOG from '@/blog.config'
|
||||
import { loadWowJS } from '@/lib/plugins/wow'
|
||||
import Link from 'next/link'
|
||||
import { Banner } from './components/Banner'
|
||||
import { SignInForm } from './components/SignInForm'
|
||||
import { SignUpForm } from './components/SignUpForm'
|
||||
import Link from 'next/link'
|
||||
import { loadWowJS } from '@/lib/plugins/wow'
|
||||
import { SVG404 } from './components/svg/SVG404'
|
||||
|
||||
/**
|
||||
* 布局框架
|
||||
@@ -46,7 +47,7 @@ import { loadWowJS } from '@/lib/plugins/wow'
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const LayoutBase = props => {
|
||||
const { children } = props
|
||||
|
||||
// 加载wow动画
|
||||
@@ -54,18 +55,22 @@ const LayoutBase = (props) => {
|
||||
loadWowJS()
|
||||
}, [])
|
||||
|
||||
return <div id='theme-starter' className={`${siteConfig('FONT_STYLE')} min-h-screen flex flex-col dark:bg-[#212b36] scroll-smooth`}>
|
||||
<Style/>
|
||||
<NavBar {...props}/>
|
||||
return (
|
||||
<div
|
||||
id='theme-starter'
|
||||
className={`${siteConfig('FONT_STYLE', BLOG.FONT_STYLE, props.NOTION_CONFIG)} min-h-screen flex flex-col dark:bg-[#212b36] scroll-smooth`}>
|
||||
<Style />
|
||||
<NavBar {...props} />
|
||||
|
||||
{children}
|
||||
{children}
|
||||
|
||||
<Footer {...props}/>
|
||||
<Footer {...props} />
|
||||
|
||||
{/* 悬浮按钮 */}
|
||||
<BackToTopButton/>
|
||||
{/* <MadeWithButton/> */}
|
||||
</div>
|
||||
{/* 悬浮按钮 */}
|
||||
<BackToTopButton />
|
||||
{/* <MadeWithButton/> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,34 +78,36 @@ const LayoutBase = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
const LayoutIndex = props => {
|
||||
const count = siteConfig('STARTER_BLOG_COUNT', 3, CONFIG)
|
||||
const posts = props?.allNavPages
|
||||
? props.allNavPages.slice(0, count)
|
||||
: []
|
||||
const posts = props?.allNavPages ? props.allNavPages.slice(0, count) : []
|
||||
return (
|
||||
<>
|
||||
{/* 英雄区 */}
|
||||
{siteConfig('STARTER_HERO_ENABLE', null, CONFIG) && <Hero/>}
|
||||
{/* 产品特性 */}
|
||||
{siteConfig('STARTER_FEATURE_ENABLE', null, CONFIG) && <Features/>}
|
||||
{/* 关于 */}
|
||||
{siteConfig('STARTER_ABOUT_ENABLE', null, CONFIG) && <About/>}
|
||||
{/* 价格 */}
|
||||
{siteConfig('STARTER_PRICING_ENABLE', null, CONFIG) && <Pricing/>}
|
||||
{/* 评价展示 */}
|
||||
{siteConfig('STARTER_TESTIMONIALS_ENABLE', null, CONFIG) && <Testimonials/>}
|
||||
{/* 常见问题 */}
|
||||
{siteConfig('STARTER_FAQ_ENABLE', null, CONFIG) && <FAQ/>}
|
||||
{/* 团队介绍 */}
|
||||
{siteConfig('团队成员区块', null, CONFIG) && <Team/>}
|
||||
{/* 博文列表 */}
|
||||
{siteConfig('STARTER_BLOG_ENABLE', null, CONFIG) && <Blog posts={posts}/>}
|
||||
{/* 联系方式 */}
|
||||
{siteConfig('STARTER_CONTACT_ENABLE', null, CONFIG) && <Contact/>}
|
||||
{/* 合作伙伴 */}
|
||||
{siteConfig('STARTER_BRANDS_ENABLE', null, CONFIG) && <Brand/>}
|
||||
</>
|
||||
<>
|
||||
{/* 英雄区 */}
|
||||
{siteConfig('STARTER_HERO_ENABLE', null, CONFIG) && <Hero />}
|
||||
{/* 产品特性 */}
|
||||
{siteConfig('STARTER_FEATURE_ENABLE', null, CONFIG) && <Features />}
|
||||
{/* 关于 */}
|
||||
{siteConfig('STARTER_ABOUT_ENABLE', null, CONFIG) && <About />}
|
||||
{/* 价格 */}
|
||||
{siteConfig('STARTER_PRICING_ENABLE', null, CONFIG) && <Pricing />}
|
||||
{/* 评价展示 */}
|
||||
{siteConfig('STARTER_TESTIMONIALS_ENABLE', null, CONFIG) && (
|
||||
<Testimonials />
|
||||
)}
|
||||
{/* 常见问题 */}
|
||||
{siteConfig('STARTER_FAQ_ENABLE', null, CONFIG) && <FAQ />}
|
||||
{/* 团队介绍 */}
|
||||
{siteConfig('STARTER_TEAM_ENABLE', null, CONFIG) && <Team />}
|
||||
{/* 博文列表 */}
|
||||
{siteConfig('STARTER_BLOG_ENABLE', null, CONFIG) && (
|
||||
<Blog posts={posts} />
|
||||
)}
|
||||
{/* 联系方式 */}
|
||||
{siteConfig('STARTER_CONTACT_ENABLE', null, CONFIG) && <Contact />}
|
||||
{/* 合作伙伴 */}
|
||||
{siteConfig('STARTER_BRANDS_ENABLE', null, CONFIG) && <Brand />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -109,106 +116,126 @@ const LayoutIndex = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSlug = (props) => {
|
||||
const LayoutSlug = props => {
|
||||
const { post } = props
|
||||
|
||||
// 如果 是 /article/[slug] 的文章路径则視情況进行重定向到另一个域名
|
||||
const router = useRouter()
|
||||
if (!post && siteConfig('STARTER_POST_REDIRECT_ENABLE', null, CONFIG) && isBrowser && router.route === '/[prefix]/[slug]') {
|
||||
const redirectUrl = siteConfig('STARTER_POST_REDIRECT_URL', null, CONFIG) + router.asPath.replace('?theme=landing', '')
|
||||
if (
|
||||
!post &&
|
||||
siteConfig('STARTER_POST_REDIRECT_ENABLE', null, CONFIG) &&
|
||||
isBrowser &&
|
||||
router.route === '/[prefix]/[slug]'
|
||||
) {
|
||||
const redirectUrl =
|
||||
siteConfig('STARTER_POST_REDIRECT_URL', null, CONFIG) +
|
||||
router.asPath.replace('?theme=landing', '')
|
||||
router.push(redirectUrl)
|
||||
return <div id='theme-starter'><Loading /></div>
|
||||
return (
|
||||
<div id='theme-starter'>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return <>
|
||||
<Banner title={post?.title} description={post?.summary}/>
|
||||
<div className="container grow">
|
||||
<div className="flex flex-wrap justify-center -mx-4">
|
||||
<div className="w-full p-4">
|
||||
<div id='container-inner' className='mx-auto'>
|
||||
<NotionPage {...props} />
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<>
|
||||
<Banner title={post?.title} description={post?.summary} />
|
||||
<div className='container grow'>
|
||||
<div className='flex flex-wrap justify-center -mx-4'>
|
||||
<div className='w-full p-4'>
|
||||
<div id='container-inner' className='mx-auto'>
|
||||
<NotionPage {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const LayoutSearch = (props) => <></>
|
||||
const LayoutSearch = props => <></>
|
||||
|
||||
/**
|
||||
* 文章归档
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutArchive = (props) => <>
|
||||
{/* 博文列表 */}
|
||||
<Blog {...props}/>
|
||||
</>
|
||||
const LayoutArchive = props => (
|
||||
<>
|
||||
{/* 博文列表 */}
|
||||
<Blog {...props} />
|
||||
</>
|
||||
)
|
||||
|
||||
/**
|
||||
* 404页面
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <>
|
||||
{/* <!-- ====== 404 Section Start --> */}
|
||||
<section className="bg-white py-20 dark:bg-dark-2 lg:py-[110px]">
|
||||
<div className="container mx-auto">
|
||||
<div className="flex flex-wrap items-center -mx-4">
|
||||
<div className="w-full px-4 md:w-5/12 lg:w-6/12">
|
||||
<div className="text-center">
|
||||
<img
|
||||
src="/images/starter/404.svg"
|
||||
alt="image"
|
||||
className="max-w-full mx-auto"
|
||||
/>
|
||||
</div>
|
||||
const Layout404 = props => {
|
||||
return (
|
||||
<>
|
||||
{/* <!-- ====== 404 Section Start --> */}
|
||||
<section className='bg-white py-20 dark:bg-dark-2 lg:py-[110px]'>
|
||||
<div className='container mx-auto'>
|
||||
<div className='flex flex-wrap items-center -mx-4'>
|
||||
<div className='w-full px-4 md:w-5/12 lg:w-6/12'>
|
||||
<div className='text-center'>
|
||||
<img
|
||||
src='/images/starter/404.svg'
|
||||
alt='image'
|
||||
className='max-w-full mx-auto'
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full px-4 md:w-7/12 lg:w-6/12 xl:w-5/12">
|
||||
<div>
|
||||
<div className="mb-8">
|
||||
<SVG404/>
|
||||
</div>
|
||||
<h3 className="mb-5 text-2xl font-semibold text-dark dark:text-white">
|
||||
{siteConfig('STARTER_404_TITLE', null, CONFIG)}
|
||||
</h3>
|
||||
<p className="mb-8 text-base text-body-color dark:text-dark-6">
|
||||
{siteConfig('STARTER_404_TEXT', null, CONFIG)}
|
||||
|
||||
</p>
|
||||
<Link href='/'
|
||||
className="py-3 text-base font-medium text-white transition rounded-md bg-dark px-7 hover:bg-primary"
|
||||
>
|
||||
{siteConfig('STARTER_404_BACK', null, CONFIG)}
|
||||
</Link>
|
||||
</div>
|
||||
<div className='w-full px-4 md:w-7/12 lg:w-6/12 xl:w-5/12'>
|
||||
<div>
|
||||
<div className='mb-8'>
|
||||
<SVG404 />
|
||||
</div>
|
||||
<h3 className='mb-5 text-2xl font-semibold text-dark dark:text-white'>
|
||||
{siteConfig('STARTER_404_TITLE', null, CONFIG)}
|
||||
</h3>
|
||||
<p className='mb-8 text-base text-body-color dark:text-dark-6'>
|
||||
{siteConfig('STARTER_404_TEXT', null, CONFIG)}
|
||||
</p>
|
||||
<Link
|
||||
href='/'
|
||||
className='py-3 text-base font-medium text-white transition rounded-md bg-dark px-7 hover:bg-primary'>
|
||||
{siteConfig('STARTER_404_BACK', null, CONFIG)}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/* <!-- ====== 404 Section End --> */}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
{/* <!-- ====== 404 Section End --> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const LayoutCategoryIndex = (props) => <></>
|
||||
const LayoutPostList = (props) => <></>
|
||||
const LayoutTagIndex = (props) => <></>
|
||||
const LayoutCategoryIndex = props => <></>
|
||||
const LayoutPostList = props => <></>
|
||||
const LayoutTagIndex = props => <></>
|
||||
|
||||
/**
|
||||
* 登录页面
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSignIn = (props) => {
|
||||
return <>
|
||||
<div className='grow mt-20'>
|
||||
<Banner title='登录' description='这里是演示页面,NotionNext目前不提供会员登录功能'/>
|
||||
<SignInForm/>
|
||||
</div>
|
||||
const LayoutSignIn = props => {
|
||||
return (
|
||||
<>
|
||||
<div className='grow mt-20'>
|
||||
<Banner
|
||||
title='登录'
|
||||
description='这里是演示页面,NotionNext目前不提供会员登录功能'
|
||||
/>
|
||||
<SignInForm />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,24 +243,29 @@ const LayoutSignIn = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSignUp = (props) => <>
|
||||
<div className='grow mt-20'>
|
||||
<Banner title='注册' description='这里是演示页面,NotionNext目前不提供会员注册功能'/>
|
||||
<SignUpForm/>
|
||||
</div>
|
||||
</>
|
||||
const LayoutSignUp = props => (
|
||||
<>
|
||||
<div className='grow mt-20'>
|
||||
<Banner
|
||||
title='注册'
|
||||
description='这里是演示页面,NotionNext目前不提供会员注册功能'
|
||||
/>
|
||||
<SignUpForm />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutPostList,
|
||||
LayoutArchive,
|
||||
LayoutBase,
|
||||
LayoutCategoryIndex,
|
||||
LayoutTagIndex,
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
LayoutSignIn,
|
||||
LayoutSignUp
|
||||
LayoutSignUp,
|
||||
LayoutSlug,
|
||||
LayoutTagIndex,
|
||||
CONFIG as THEME_CONFIG
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user