Merge branch 'main' into original-fix

This commit is contained in:
tangly1024
2025-01-01 15:49:15 +08:00
committed by GitHub
355 changed files with 16915 additions and 6775 deletions

View File

@@ -1,195 +1,179 @@
/* eslint-disable @next/next/no-img-element */
/* eslint-disable react/no-unescaped-entities */
import { siteConfig } from '@/lib/config'
import CONFIG from '../config'
import Link from 'next/link'
/**
* 首页的关于模块
*/
export const About = () => {
return <>
{/* <!-- ====== About Section Start --> */}
<section
id="about"
className="bg-gray-1 pb-8 pt-20 dark:bg-dark-2 lg:pb-[70px] lg:pt-[120px]"
>
<div className="container">
<div className="wow fadeInUp" data-wow-delay=".2s">
<div className="-mx-4 flex flex-wrap items-center">
return (
<>
{/* <!-- ====== About Section Start --> */}
<section
id='about'
className='bg-gray-1 pb-8 pt-20 dark:bg-dark-2 lg:pb-[70px] lg:pt-[120px]'>
<div className='container'>
<div className='wow fadeInUp' data-wow-delay='.2s'>
<div className='-mx-4 flex flex-wrap items-center'>
{/* 左侧的文字说明板块 */}
<div className='w-full px-4 lg:w-1/2'>
<div className='mb-12 max-w-[540px] lg:mb-0'>
<h2 className='mb-5 text-3xl font-bold leading-tight text-dark dark:text-white sm:text-[40px] sm:leading-[1.2]'>
{siteConfig('STARTER_ABOUT_TITLE')}
</h2>
<p
className='mb-10 text-base leading-relaxed text-body-color dark:text-dark-6'
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_ABOUT_TEXT')
}}></p>
{/* 左侧的文字说明板块 */}
<div className="w-full px-4 lg:w-1/2">
<div className="mb-12 max-w-[540px] lg:mb-0">
<h2
className="mb-5 text-3xl font-bold leading-tight text-dark dark:text-white sm:text-[40px] sm:leading-[1.2]"
>
{siteConfig('STARTER_ABOUT_TITLE', null, CONFIG)}
</h2>
<p className="mb-10 text-base leading-relaxed text-body-color dark:text-dark-6"
dangerouslySetInnerHTML={
{ __html: siteConfig('STARTER_ABOUT_TEXT', null, CONFIG) }
}></p>
<a
href={siteConfig('STARTER_ABOUT_BUTTON_URL', null, CONFIG)}
className="inline-flex items-center justify-center rounded-md border border-primary bg-primary px-7 py-3 text-center text-base font-medium text-white hover:border-blue-dark hover:bg-blue-dark"
>
{siteConfig('STARTER_ABOUT_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
{/* 右侧的图片海报 */}
<div className="w-full px-4 lg:w-1/2">
<div className="-mx-2 flex flex-wrap sm:-mx-4 lg:-mx-2 xl:-mx-4">
<div className="w-full px-2 sm:w-1/2 sm:px-4 lg:px-2 xl:px-4">
<div
className="mb-4 sm:mb-8 sm:h-[400px] md:h-[540px] lg:h-[400px] xl:h-[500px]"
>
<img
src={siteConfig('STARTER_ABOUT_IMAGE_1', null, CONFIG)}
alt="about image"
className="h-full w-full object-cover object-center"
/>
</div>
<Link
href={siteConfig('STARTER_ABOUT_BUTTON_URL', '')}
className='inline-flex items-center justify-center rounded-md border border-primary bg-primary px-7 py-3 text-center text-base font-medium text-white hover:border-blue-dark hover:bg-blue-dark'>
{siteConfig('STARTER_ABOUT_BUTTON_TEXT')}
</Link>
</div>
</div>
<div className="w-full px-2 sm:w-1/2 sm:px-4 lg:px-2 xl:px-4">
<div
className="mb-4 sm:mb-8 sm:h-[220px] md:h-[346px] lg:mb-4 lg:h-[225px] xl:mb-8 xl:h-[310px]"
>
<img
src={siteConfig('STARTER_ABOUT_IMAGE_2', null, CONFIG)}
alt="about image"
className="h-full w-full object-cover object-center"
/>
{/* 右侧的图片海报 */}
<div className='w-full px-4 lg:w-1/2'>
<div className='-mx-2 flex flex-wrap sm:-mx-4 lg:-mx-2 xl:-mx-4'>
<div className='w-full px-2 sm:w-1/2 sm:px-4 lg:px-2 xl:px-4'>
<div className='mb-4 sm:mb-8 sm:h-[400px] md:h-[540px] lg:h-[400px] xl:h-[500px]'>
<img
src={siteConfig('STARTER_ABOUT_IMAGE_1')}
alt='about image'
className='h-full w-full object-cover object-center'
/>
</div>
</div>
<div
className="relative z-10 mb-4 flex items-center justify-center overflow-hidden bg-primary px-6 py-12 sm:mb-8 sm:h-[160px] sm:p-5 lg:mb-4 xl:mb-8"
>
<div>
<span className="block text-5xl font-extrabold text-white">
{siteConfig('STARTER_ABOUT_TIPS_1', null, CONFIG)}
</span>
<span className="block text-base font-semibold text-white">
{siteConfig('STARTER_ABOUT_TIPS_2', null, CONFIG)}
</span>
<span
className="block text-base font-medium text-white text-opacity-70"
>
{siteConfig('STARTER_ABOUT_TIPS_3', null, CONFIG)}
</span>
<div className='w-full px-2 sm:w-1/2 sm:px-4 lg:px-2 xl:px-4'>
<div className='mb-4 sm:mb-8 sm:h-[220px] md:h-[346px] lg:mb-4 lg:h-[225px] xl:mb-8 xl:h-[310px]'>
<img
src={siteConfig('STARTER_ABOUT_IMAGE_2')}
alt='about image'
className='h-full w-full object-cover object-center'
/>
</div>
<div>
<span className="absolute left-0 top-0 -z-10">
<svg
width="106"
height="144"
viewBox="0 0 106 144"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
opacity="0.1"
x="-67"
y="47.127"
width="113.378"
height="131.304"
transform="rotate(-42.8643 -67 47.127)"
fill="url(#paint0_linear_1416_214)"
/>
<defs>
<linearGradient
id="paint0_linear_1416_214"
x1="-10.3111"
y1="47.127"
x2="-10.3111"
y2="178.431"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="white" />
<stop
offset="1"
stopColor="white"
stopOpacity="0"
/>
</linearGradient>
</defs>
</svg>
</span>
<span className="absolute right-0 top-0 -z-10">
<svg
width="130"
height="97"
viewBox="0 0 130 97"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
opacity="0.1"
x="0.86792"
y="-6.67725"
width="155.563"
height="140.614"
transform="rotate(-42.8643 0.86792 -6.67725)"
fill="url(#paint0_linear_1416_215)"
/>
<defs>
<linearGradient
id="paint0_linear_1416_215"
x1="78.6495"
y1="-6.67725"
x2="78.6495"
y2="133.937"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="white" />
<stop
offset="1"
stopColor="white"
stopOpacity="0"
/>
</linearGradient>
</defs>
</svg>
</span>
<span className="absolute bottom-0 right-0 -z-10">
<svg
width="175"
height="104"
viewBox="0 0 175 104"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
opacity="0.1"
x="175.011"
y="108.611"
width="101.246"
height="148.179"
transform="rotate(137.136 175.011 108.611)"
fill="url(#paint0_linear_1416_216)"
/>
<defs>
<linearGradient
id="paint0_linear_1416_216"
x1="225.634"
y1="108.611"
x2="225.634"
y2="256.79"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="white" />
<stop
offset="1"
stopColor="white"
stopOpacity="0"
/>
</linearGradient>
</defs>
</svg>
</span>
<div className='relative z-10 mb-4 flex items-center justify-center overflow-hidden bg-primary px-6 py-12 sm:mb-8 sm:h-[160px] sm:p-5 lg:mb-4 xl:mb-8'>
<div>
<span className='block text-5xl font-extrabold text-white'>
{siteConfig('STARTER_ABOUT_TIPS_1')}
</span>
<span className='block text-base font-semibold text-white'>
{siteConfig('STARTER_ABOUT_TIPS_2')}
</span>
<span className='block text-base font-medium text-white text-opacity-70'>
{siteConfig('STARTER_ABOUT_TIPS_3')}
</span>
</div>
<div>
<span className='absolute left-0 top-0 -z-10'>
<svg
width='106'
height='144'
viewBox='0 0 106 144'
fill='none'
xmlns='http://www.w3.org/2000/svg'>
<rect
opacity='0.1'
x='-67'
y='47.127'
width='113.378'
height='131.304'
transform='rotate(-42.8643 -67 47.127)'
fill='url(#paint0_linear_1416_214)'
/>
<defs>
<linearGradient
id='paint0_linear_1416_214'
x1='-10.3111'
y1='47.127'
x2='-10.3111'
y2='178.431'
gradientUnits='userSpaceOnUse'>
<stop stopColor='white' />
<stop
offset='1'
stopColor='white'
stopOpacity='0'
/>
</linearGradient>
</defs>
</svg>
</span>
<span className='absolute right-0 top-0 -z-10'>
<svg
width='130'
height='97'
viewBox='0 0 130 97'
fill='none'
xmlns='http://www.w3.org/2000/svg'>
<rect
opacity='0.1'
x='0.86792'
y='-6.67725'
width='155.563'
height='140.614'
transform='rotate(-42.8643 0.86792 -6.67725)'
fill='url(#paint0_linear_1416_215)'
/>
<defs>
<linearGradient
id='paint0_linear_1416_215'
x1='78.6495'
y1='-6.67725'
x2='78.6495'
y2='133.937'
gradientUnits='userSpaceOnUse'>
<stop stopColor='white' />
<stop
offset='1'
stopColor='white'
stopOpacity='0'
/>
</linearGradient>
</defs>
</svg>
</span>
<span className='absolute bottom-0 right-0 -z-10'>
<svg
width='175'
height='104'
viewBox='0 0 175 104'
fill='none'
xmlns='http://www.w3.org/2000/svg'>
<rect
opacity='0.1'
x='175.011'
y='108.611'
width='101.246'
height='148.179'
transform='rotate(137.136 175.011 108.611)'
fill='url(#paint0_linear_1416_216)'
/>
<defs>
<linearGradient
id='paint0_linear_1416_216'
x1='225.634'
y1='108.611'
x2='225.634'
y2='256.79'
gradientUnits='userSpaceOnUse'>
<stop stopColor='white' />
<stop
offset='1'
stopColor='white'
stopOpacity='0'
/>
</linearGradient>
</defs>
</svg>
</span>
</div>
</div>
</div>
</div>
@@ -197,8 +181,8 @@ export const About = () => {
</div>
</div>
</div>
</div>
</section>
{/* <!-- ====== About Section End --> */}
</section>
{/* <!-- ====== About Section End --> */}
</>
)
}

View File

@@ -0,0 +1,53 @@
import { useGlobal } from '@/lib/global'
import { useEffect, useRef } from 'react'
/**
* 加密文章校验组件
* @param {password, validPassword} props
* @param password 正确的密码
* @param validPassword(bool) 回调函数校验正确回调入参为true
* @returns
*/
export const ArticleLock = props => {
const { validPassword } = props
const { locale } = useGlobal()
const submitPassword = () => {
const p = document.getElementById('password')
if (!validPassword(p?.value)) {
const tips = document.getElementById('tips')
if (tips) {
tips.innerHTML = ''
tips.innerHTML = `<div class='text-red-500 animate__shakeX animate__animated'>${locale.COMMON.PASSWORD_ERROR}</div>`
}
}
}
const passwordInputRef = useRef(null)
useEffect(() => {
// 选中密码输入框并将其聚焦
passwordInputRef.current.focus()
}, [])
return <div id='container' className='w-full flex justify-center items-center h-96 '>
<div className='text-center space-y-3'>
<div className='font-bold'>{locale.COMMON.ARTICLE_LOCK_TIPS}</div>
<div className='flex'>
<input id="password" type='password'
onKeyDown={(e) => {
if (e.key === 'Enter') {
submitPassword()
}
}}
ref={passwordInputRef} // 绑定ref到passwordInputRef变量
className='outline-none w-full text-sm pl-5 rounded-l transition focus:shadow-lg font-light leading-10 text-black dark:bg-gray-500 bg-gray-50'
></input>
<div onClick={submitPassword} className="px-3 whitespace-nowrap cursor-pointer items-center justify-center py-2 rounded-r duration-300 bg-gray-300" >
<i className={'duration-200 cursor-pointer fas fa-key dark:text-black'} >&nbsp;{locale.COMMON.SUBMIT}</i>
</div>
</div>
<div id='tips'>
</div>
</div>
</div>
}

View File

@@ -1,41 +1,17 @@
import throttle from 'lodash.throttle';
import throttle from 'lodash.throttle'
import { useCallback, useEffect } from 'react'
/**
* 回顶按钮
* @returns
*/
export const BackToTopButton = () => {
useEffect(() => {
// ====== scroll top js
function scrollTo(element, to = 0, duration = 500) {
const start = element.scrollTop;
const change = to - start;
const increment = 20;
let currentTime = 0;
const animateScroll = () => {
currentTime += increment;
const val = Math.easeInOutQuad(currentTime, start, change, duration);
element.scrollTop = val;
if (currentTime < duration) {
setTimeout(animateScroll, increment);
}
};
animateScroll();
}
Math.easeInOutQuad = function (t, b, c, d) {
t /= d / 2;
if (t < 1) return (c / 2) * t * t + b;
t--;
return (-c / 2) * (t * (t - 2) - 1) + b;
};
const backToTop = document.querySelector('.back-to-top')
if (backToTop) {
backToTop.onclick = () => {
scrollTo(document.documentElement);
};
t /= d / 2
if (t < 1) return (c / 2) * t * t + b
t--
return (-c / 2) * (t * (t - 2) - 1) + b
}
window.addEventListener('scroll', navBarScollListener)
@@ -48,20 +24,52 @@ export const BackToTopButton = () => {
const throttleMs = 200
const navBarScollListener = useCallback(
throttle(() => {
const scrollY = window.scrollY;
const scrollY = window.scrollY
// 显示或隐藏返回顶部按钮
const backToTop = document.querySelector('.back-to-top');
const backToTop = document.querySelector('.back-to-top')
if (backToTop) {
backToTop.style.display = scrollY > 50 ? 'flex' : 'none';
backToTop.style.display = scrollY > 50 ? 'flex' : 'none'
}
}, throttleMs)
)
return <>
{/* <!-- ====== Back To Top Start --> */}
<a className="back-to-top fixed bottom-16 left-auto right-8 z-[999] hidden h-10 w-10 items-center justify-center rounded-md bg-primary text-white shadow-md transition duration-300 ease-in-out hover:bg-dark">
<span className="mt-[6px] h-3 w-3 rotate-45 border-l border-t border-white" ></span>
</a>
{/* <!-- ====== Back To Top End --> */}
// ====== scroll top js
function scrollTo(element, to = 0, duration = 500) {
const start = element.scrollTop
const change = to - start
const increment = 20
let currentTime = 0
const animateScroll = () => {
currentTime += increment
const val = Math.easeInOutQuad(currentTime, start, change, duration)
element.scrollTop = val
if (currentTime < duration) {
setTimeout(animateScroll, increment)
}
}
animateScroll()
}
function scrollTop() {
if (document) {
scrollTo(document.documentElement)
}
}
return (
<>
{/* <!-- ====== Back To Top Start --> */}
<a
onClick={scrollTop}
className='back-to-top cursor-pointer fixed bottom-16 left-auto right-8 z-[999] hidden h-10 w-10 items-center justify-center rounded-md bg-primary text-white shadow-md transition duration-300 ease-in-out hover:bg-dark'>
<span className='mt-[6px] h-3 w-3 rotate-45 border-l border-t border-white'></span>
</a>
{/* <!-- ====== Back To Top End --> */}
</>
)
}

View File

@@ -1,30 +1,25 @@
/**
* 详情页面顶部
* 页面顶部宣传栏
* @returns
*/
export const Banner = ({ title, description }) => {
return <>
{/* <!-- ====== Banner Section Start --> */}
<div
className="relative z-10 overflow-hidden pb-[60px] pt-[120px] dark:bg-dark md:pt-[130px] lg:pt-[160px]"
>
<div
className="absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-stroke/0 via-stroke to-stroke/0 dark:via-dark-3"
></div>
<div className="container">
<div className="flex flex-wrap items-center -mx-4">
<div className="w-full px-4">
<div className="text-center">
<h1
className="mb-4 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]"
>
{title}
</h1>
<p className="mb-5 text-base text-body-color dark:text-dark-6">
{description}
</p>
return (
<>
{/* <!-- ====== Banner Section Start --> */}
<div className='relative z-10 overflow-hidden pb-[60px] pt-[120px] dark:bg-dark md:pt-[130px] lg:pt-[160px]'>
<div className='absolute bottom-0 left-0 w-full h-px bg-gradient-to-r from-stroke/0 via-stroke to-stroke/0 dark:via-dark-3'></div>
<div className='container'>
<div className='flex flex-wrap items-center -mx-4'>
<div className='w-full px-4'>
<div className='text-center'>
<h1 className='mb-4 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]'>
{title}
</h1>
<p className='mb-5 text-base text-body-color dark:text-dark-6'>
{description}
</p>
{/* <ul className="flex items-center justify-center gap-[10px]">
{/* <ul className="flex items-center justify-center gap-[10px]">
<li>
<a
href="index.html"
@@ -43,11 +38,12 @@ export const Banner = ({ title, description }) => {
</a>
</li>
</ul> */}
</div>
</div>
</div>
</div>
</div>
</div>
{/* <!-- ====== Banner Section End --> */}
{/* <!-- ====== Banner Section End --> */}
</>
)
}

View File

@@ -1,7 +1,6 @@
/* eslint-disable @next/next/no-img-element */
import { siteConfig } from '@/lib/config'
import Link from 'next/link'
import CONFIG from '../config'
/**
* 博文列表
@@ -19,14 +18,14 @@ export const Blog = ({ posts }) => {
<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_BLOG_TITLE', null, CONFIG)}
{siteConfig('STARTER_BLOG_TITLE')}
</span>
<h2 className='mb-4 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]'>
{siteConfig('STARTER_BLOG_TEXT_1', null, CONFIG)}
{siteConfig('STARTER_BLOG_TEXT_1')}
</h2>
<p
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_BLOG_TEXT_2', null, CONFIG)
__html: siteConfig('STARTER_BLOG_TEXT_2')
}}
className='text-base text-body-color dark:text-dark-6'></p>
</div>
@@ -41,13 +40,15 @@ export const Blog = ({ posts }) => {
className='wow fadeInUp group mb-10'
data-wow-delay='.1s'>
<div className='mb-8 overflow-hidden rounded-[5px]'>
<Link href={item?.href} className='block'>
<img
src={item.pageCoverThumbnail}
alt={item.title}
className='w-full transition group-hover:rotate-6 group-hover:scale-125'
/>
</Link>
{item.pageCoverThumbnail && (
<Link href={item?.href} className='block'>
<img
src={item.pageCoverThumbnail}
alt={item.title}
className='w-full transition group-hover:rotate-6 group-hover:scale-125'
/>
</Link>
)}
</div>
<div>
<span className='mb-6 inline-block rounded-[5px] bg-primary px-4 py-0.5 text-center text-xs font-medium leading-loose text-white'>

View File

@@ -1,37 +1,39 @@
/* eslint-disable @next/next/no-img-element */
import CONFIG from '../config'
import { siteConfig } from '@/lib/config'
/**
* 合作伙伴
* @returns
*/
export const Brand = () => {
return <>
{/* <!-- ====== Brands Section Start --> */}
<section className="pb-20 dark:bg-dark">
<div className="container px-4">
<div
className="-mx-4 flex flex-wrap items-center justify-center gap-8 xl:gap-11"
>
{CONFIG.STARTER_BRANDS?.map((item, index) => {
return <a key={index} href={item.URL}>
<img
src={item.IMAGE}
alt={item.TITLE}
className="dark:hidden"
/>
<img
src={item.IMAGE_WHITE}
alt={item.TITLE}
className="hidden dark:block"
/>
</a>
})}
const brands = siteConfig('STARTER_BRANDS')
return (
<>
{/* <!-- ====== Brands Section Start --> */}
<section className='py-20 dark:bg-dark'>
<div className='container px-4'>
<div className='-mx-4 flex flex-wrap items-center justify-center gap-8 xl:gap-11'>
{brands?.map((item, index) => {
return (
<a key={index} href={item.URL}>
<img
src={item.IMAGE}
alt={item.TITLE}
className='dark:hidden'
/>
<img
src={item.IMAGE_WHITE}
alt={item.TITLE}
className='hidden dark:block'
/>
</a>
)
})}
</div>
</div>
</div>
</section>
{/* <!-- ====== Brands Section End --> */}
</section>
{/* <!-- ====== Brands Section End --> */}
</>
)
}

View File

@@ -1,106 +1,112 @@
import { siteConfig } from '@/lib/config'
import Link from 'next/link'
/**
* CTA用于创建一个呼吁用户行动的部分Call To Action简称 CTA
* 该组件通过以下方式激励用户进行特定操作
* 用户的公告栏内容将在此显示
**/
export const CTA = () => {
return <>
{/* <!-- ====== CTA Section Start --> */}
<section
className="relative z-10 overflow-hidden bg-primary py-20 lg:py-[115px]"
>
<div className="container mx-auto">
<div className="relative overflow-hidden">
<div className="-mx-4 flex flex-wrap items-stretch">
<div className="w-full px-4">
<div className="mx-auto max-w-[570px] text-center">
<h2
className="mb-2.5 text-3xl font-bold text-white md:text-[38px] md:leading-[1.44]"
>
<span>What Are You Looking For?</span>
<span className="text-3xl font-normal md:text-[40px]">
Get Started Now
</span>
</h2>
<p
className="mx-auto mb-6 max-w-[515px] text-base leading-[1.5] text-white"
>
There are many variations of passages of Lorem Ipsum but the
majority have suffered in some form.
</p>
<a
className="inline-block rounded-md border border-transparent bg-secondary px-7 py-3 text-base font-medium text-white transition hover:bg-[#0BB489]"
>
Start using Play
</a>
if (!siteConfig('STARTER_CTA_ENABLE')) {
return <></>
}
return (
<>
{/* <!-- ====== CTA Section Start --> */}
<section className='relative z-10 overflow-hidden bg-primary py-20 lg:py-[115px]'>
<div className='container mx-auto'>
<div className='relative overflow-hidden'>
<div className='-mx-4 flex flex-wrap items-stretch'>
<div className='w-full px-4'>
<div className='mx-auto max-w-[570px] text-center'>
<h2 className='mb-2.5 text-3xl font-bold text-white md:text-[38px] md:leading-[1.44]'>
<span>{siteConfig('STARTER_CTA_TITLE')}</span>
<span className='text-3xl font-normal md:text-[40px]'>
{siteConfig('STARTER_CTA_TITLE_2')}
</span>
</h2>
<p className='mx-auto mb-6 max-w-[515px] text-base leading-[1.5] text-white'>
{siteConfig('STARTER_CTA_DESCRIOTN')}
</p>
{siteConfig('STARTER_CTA_BUTTON') && (
<>
<Link
href={siteConfig('STARTER_CTA_BUTTON_URL', '')}
className='inline-block rounded-md border border-transparent bg-secondary px-7 py-3 text-base font-medium text-white transition hover:bg-[#0BB489]'>
{siteConfig('STARTER_CTA_BUTTON_TEXT')}
</Link>
</>
)}
</div>
</div>
</div>
</div>
</div>
</div>
<div>
<span className="absolute left-0 top-0">
<svg
width="495"
height="470"
viewBox="0 0 495 470"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="55"
cy="442"
r="138"
stroke="white"
stroke-opacity="0.04"
stroke-width="50"
/>
<circle
cx="446"
r="39"
stroke="white"
stroke-opacity="0.04"
stroke-width="20"
/>
<path
d="M245.406 137.609L233.985 94.9852L276.609 106.406L245.406 137.609Z"
stroke="white"
stroke-opacity="0.08"
stroke-width="12"
/>
</svg>
</span>
<span className="absolute bottom-0 right-0">
<svg
width="493"
height="470"
viewBox="0 0 493 470"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="462"
cy="5"
r="138"
stroke="white"
stroke-opacity="0.04"
stroke-width="50"
/>
<circle
cx="49"
cy="470"
r="39"
stroke="white"
stroke-opacity="0.04"
stroke-width="20"
/>
<path
d="M222.393 226.701L272.808 213.192L259.299 263.607L222.393 226.701Z"
stroke="white"
stroke-opacity="0.06"
stroke-width="13"
/>
</svg>
</span>
</div>
</section>
{/* <!-- ====== CTA Section End --> */}
<div>
<span className='absolute left-0 top-0'>
<svg
width='495'
height='470'
viewBox='0 0 495 470'
fill='none'
xmlns='http://www.w3.org/2000/svg'>
<circle
cx='55'
cy='442'
r='138'
stroke='white'
stroke-opacity='0.04'
stroke-width='50'
/>
<circle
cx='446'
r='39'
stroke='white'
stroke-opacity='0.04'
stroke-width='20'
/>
<path
d='M245.406 137.609L233.985 94.9852L276.609 106.406L245.406 137.609Z'
stroke='white'
stroke-opacity='0.08'
stroke-width='12'
/>
</svg>
</span>
<span className='absolute bottom-0 right-0'>
<svg
width='493'
height='470'
viewBox='0 0 493 470'
fill='none'
xmlns='http://www.w3.org/2000/svg'>
<circle
cx='462'
cy='5'
r='138'
stroke='white'
stroke-opacity='0.04'
stroke-width='50'
/>
<circle
cx='49'
cy='470'
r='39'
stroke='white'
stroke-opacity='0.04'
stroke-width='20'
/>
<path
d='M222.393 226.701L272.808 213.192L259.299 263.607L222.393 226.701Z'
stroke='white'
stroke-opacity='0.06'
stroke-width='13'
/>
</svg>
</span>
</div>
</section>
{/* <!-- ====== CTA Section End --> */}
</>
)
}

View File

@@ -5,6 +5,7 @@ import { SVGLocation } from './svg/SVGLocation'
/* eslint-disable react/no-unescaped-entities */
export const Contact = () => {
const url = siteConfig('STARTER_CONTACT_MSG_EXTERNAL_URL')
return (
<>
{/* <!-- ====== Contact Start ====== --> */}
@@ -18,10 +19,10 @@ export const Contact = () => {
<div className='ud-contact-content-wrapper'>
<div className='ud-contact-title mb-12 lg:mb-[150px]'>
<span className='mb-6 block text-base font-medium text-dark dark:text-white'>
{siteConfig('STARTER_CONTACT_TITLE', null, CONFIG)}
{siteConfig('STARTER_CONTACT_TITLE')}
</span>
<h2 className='max-w-[260px] text-[35px] font-semibold leading-[1.14] text-dark dark:text-white'>
{siteConfig('STARTER_CONTACT_TEXT', null, CONFIG)}
{siteConfig('STARTER_CONTACT_TEXT')}
</h2>
</div>
<div className='mb-12 flex flex-wrap justify-between lg:mb-0'>
@@ -59,7 +60,7 @@ export const Contact = () => {
)}
</h5>
<p className='text-base text-body-color dark:text-dark-6'>
{siteConfig('STARTER_CONTACT_EMAIL_TEXT', null, CONFIG)}
{siteConfig('STARTER_CONTACT_EMAIL_TEXT')}
</p>
</div>
</div>
@@ -67,7 +68,7 @@ export const Contact = () => {
</div>
</div>
{siteConfig('STARTER_CONTACT_MSG_EXTERNAL_URL', null, CONFIG) && (
{url && url !== '' && (
<>
{/* 联系方式右侧留言 */}
<div className='w-full px-4 lg:w-5/12 xl:w-4/12'>

View File

@@ -1,137 +1,120 @@
import { siteConfig } from '@/lib/config';
import { siteConfig } from '@/lib/config'
import { useEffect } from 'react'
import CONFIG from '../config';
import { SVGQuestion } from './svg/SVGQuestion';
import { SVGCircleBG } from './svg/SVGCircleBG';
import { SVGCircleBG } from './svg/SVGCircleBG'
import { SVGQuestion } from './svg/SVGQuestion'
export const FAQ = () => {
useEffect(() => {
// ===== Faq accordion
const faqs = document.querySelectorAll('.single-faq');
faqs.forEach((el) => {
const faqs = document.querySelectorAll('.single-faq')
faqs.forEach(el => {
el.querySelector('.faq-btn').addEventListener('click', () => {
el.querySelector('.icon').classList.toggle('rotate-180');
el.querySelector('.faq-content').classList.toggle('hidden');
});
});
el.querySelector('.icon').classList.toggle('rotate-180')
el.querySelector('.faq-content').classList.toggle('hidden')
})
})
})
return <>
return (
<>
{/* <!-- ====== FAQ Section Start --> */}
<section
className="relative z-20 overflow-hidden bg-white pb-8 pt-20 dark:bg-dark lg:pb-[50px] 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-[520px] text-center">
<span className="mb-2 block text-lg font-semibold text-primary">
{siteConfig('STARTER_FAQ_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_FAQ_TEXT_1', null, CONFIG)}
</h2>
<p
className="mx-auto max-w-[485px] text-base text-body-color dark:text-dark-6"
>
{siteConfig('STARTER_FAQ_TEXT_2', null, CONFIG)}
</p>
<section className='relative overflow-hidden bg-white pb-8 pt-20 dark:bg-dark lg:pb-[50px] 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-[520px] text-center'>
<span className='mb-2 block text-lg font-semibold text-primary'>
{siteConfig('STARTER_FAQ_TITLE')}
</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_FAQ_TEXT_1')}
</h2>
<p className='mx-auto max-w-[485px] text-base text-body-color dark:text-dark-6'>
{siteConfig('STARTER_FAQ_TEXT_2')}
</p>
</div>
</div>
</div>
<div className='-mx-4 flex flex-wrap'>
<div className='w-full px-4 lg:w-1/2'>
<div className='mb-12 flex lg:mb-[70px]'>
<div className='mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]'>
<SVGQuestion />
</div>
<div className='w-full'>
<h3 className='mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl'>
{siteConfig('STARTER_FAQ_1_QUESTION')}
</h3>
<p
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_FAQ_1_ANSWER')
}}
className='text-base text-body-color dark:text-dark-6'></p>
</div>
</div>
<div className='mb-12 flex lg:mb-[70px]'>
<div className='mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]'>
<SVGQuestion />
</div>
<div className='w-full'>
<h3 className='mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl'>
{siteConfig('STARTER_FAQ_2_QUESTION')}
</h3>
<p
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_FAQ_2_ANSWER')
}}
className='text-base text-body-color dark:text-dark-6'></p>
</div>
</div>
</div>
<div className='w-full px-4 lg:w-1/2'>
<div className='mb-12 flex lg:mb-[70px]'>
<div className='mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]'>
<SVGQuestion />
</div>
<div className='w-full'>
<h3 className='mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl'>
{siteConfig('STARTER_FAQ_3_QUESTION')}
</h3>
<p
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_FAQ_3_ANSWER')
}}
className='text-base text-body-color dark:text-dark-6'></p>
</div>
</div>
<div className='mb-12 flex lg:mb-[70px]'>
<div className='mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]'>
<SVGQuestion />
</div>
<div className='w-full'>
<h3 className='mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl'>
{siteConfig('STARTER_FAQ_4_QUESTION')}
</h3>
<p
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_FAQ_4_ANSWER')
}}
className='text-base text-body-color dark:text-dark-6'></p>
</div>
</div>
</div>
</div>
</div>
<div className="-mx-4 flex flex-wrap">
<div className="w-full px-4 lg:w-1/2">
<div className="mb-12 flex lg:mb-[70px]">
<div
className="mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]"
>
<SVGQuestion/>
</div>
<div className="w-full">
<h3
className="mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl"
>
{siteConfig('STARTER_FAQ_1_QUESTION', null, CONFIG)}
</h3>
<p dangerouslySetInnerHTML={
{ __html: siteConfig('STARTER_FAQ_1_ANSWER', null, CONFIG) }
} className="text-base text-body-color dark:text-dark-6">
</p>
</div>
</div>
<div className="mb-12 flex lg:mb-[70px]">
<div
className="mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]"
>
<SVGQuestion/>
</div>
<div className="w-full">
<h3
className="mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl"
>
{siteConfig('STARTER_FAQ_2_QUESTION', null, CONFIG)}
</h3>
<p dangerouslySetInnerHTML={
{ __html: siteConfig('STARTER_FAQ_2_ANSWER', null, CONFIG) }
} className="text-base text-body-color dark:text-dark-6">
</p>
</div>
</div>
</div>
<div className="w-full px-4 lg:w-1/2">
<div className="mb-12 flex lg:mb-[70px]">
<div
className="mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]"
>
<SVGQuestion/>
</div>
<div className="w-full">
<h3
className="mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl"
>
{siteConfig('STARTER_FAQ_3_QUESTION', null, CONFIG)}
</h3>
<p dangerouslySetInnerHTML={
{ __html: siteConfig('STARTER_FAQ_3_ANSWER', null, CONFIG) }
} className="text-base text-body-color dark:text-dark-6">
</p>
</div>
</div>
<div className="mb-12 flex lg:mb-[70px]">
<div
className="mr-4 flex h-[50px] w-full max-w-[50px] items-center justify-center rounded-xl bg-primary text-white sm:mr-6 sm:h-[60px] sm:max-w-[60px]"
>
<SVGQuestion/>
</div>
<div className="w-full">
<h3
className="mb-6 text-xl font-semibold text-dark dark:text-white sm:text-2xl lg:text-xl xl:text-2xl"
>
{siteConfig('STARTER_FAQ_4_QUESTION', null, CONFIG)}
</h3>
<p dangerouslySetInnerHTML={
{ __html: siteConfig('STARTER_FAQ_4_ANSWER', null, CONFIG) }
} className="text-base text-body-color dark:text-dark-6">
</p>
</div>
</div>
</div>
{/* 背景图案 */}
<div>
<span className='absolute left-4 top-4 -z-[1]'>
<SVGCircleBG />
</span>
<span className='absolute bottom-4 right-4 -z-[1]'>
<SVGCircleBG />
</span>
</div>
</div>
{/* 背景图案 */}
<div>
<span className="absolute left-4 top-4 -z-[1]">
<SVGCircleBG/>
</span>
<span className="absolute bottom-4 right-4 -z-[1]">
<SVGCircleBG/>
</span>
</div>
</section>
{/* <!-- ====== FAQ Section End --> */}
</section>
{/* <!-- ====== FAQ Section End --> */}
</>
)
}

View File

@@ -1,135 +1,115 @@
import CONFIG from '../config'
import { siteConfig } from '@/lib/config';
import { SVGGifts } from './svg/SVGGifts';
import { SVGTemplate } from './svg/SVGTemplate';
import { SVGDesign } from './svg/SVGDesign';
import { SVGEssential } from './svg/SVGEssential';
import { siteConfig } from '@/lib/config'
import { SVGDesign } from './svg/SVGDesign'
import { SVGEssential } from './svg/SVGEssential'
import { SVGGifts } from './svg/SVGGifts'
import { SVGTemplate } from './svg/SVGTemplate'
import Link from 'next/link'
/**
* 产品特性相关,将显示在首页中
* @returns
*/
export const Features = () => {
return <>
{/* <!-- ====== Features Section Start --> */}
<section className="pb-8 pt-20 dark:bg-dark lg:pb-[70px] lg:pt-[120px]">
<div className="container">
<div className="-mx-4 flex flex-wrap">
<div className="w-full px-4">
<div className="mx-auto mb-12 max-w-[485px] text-center lg:mb-[70px]">
<span className="mb-2 block text-lg font-semibold text-primary">
{siteConfig('STARTER_FEATURE_TITLE', null, CONFIG)}
</span>
<h2
className="mb-3 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]"
>
{siteConfig('STARTER_FEATURE_TEXT_1', null, CONFIG)}
</h2>
<p className="text-base text-body-color dark:text-dark-6">
{siteConfig('STARTER_FEATURE_TEXT_2', null, CONFIG)}
</p>
return (
<>
{/* <!-- ====== Features Section Start --> */}
<section className='pb-8 pt-20 dark:bg-dark lg:pb-[70px] lg:pt-[120px]'>
<div className='container'>
<div className='-mx-4 flex flex-wrap'>
<div className='w-full px-4'>
<div className='mx-auto mb-12 max-w-[485px] text-center lg:mb-[70px]'>
<span className='mb-2 block text-lg font-semibold text-primary'>
{siteConfig('STARTER_FEATURE_TITLE')}
</span>
<h2 className='mb-3 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]'>
{siteConfig('STARTER_FEATURE_TEXT_1')}
</h2>
<p className='text-base text-body-color dark:text-dark-6'>
{siteConfig('STARTER_FEATURE_TEXT_2')}
</p>
</div>
</div>
</div>
<div className='-mx-4 flex flex-wrap'>
<div className='w-full px-4 md:w-1/2 lg:w-1/4'>
<div className='wow fadeInUp group mb-12' data-wow-delay='.1s'>
<div className='relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary'>
<span className='absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45'></span>
<SVGGifts />
</div>
<h4 className='mb-3 text-xl font-bold text-dark dark:text-white'>
{siteConfig('STARTER_FEATURE_1_TITLE_1')}
</h4>
<p className='mb-8 text-body-color dark:text-dark-6 lg:mb-9'>
{siteConfig('STARTER_FEATURE_1_TEXT_1')}
</p>
<Link
href={siteConfig('STARTER_FEATURE_1_BUTTON_URL', '')}
className='text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary'>
{siteConfig('STARTER_FEATURE_1_BUTTON_TEXT')}
</Link>
</div>
</div>
<div className='w-full px-4 md:w-1/2 lg:w-1/4'>
<div className='wow fadeInUp group mb-12' data-wow-delay='.15s'>
<div className='relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary'>
<span className='absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45'></span>
<SVGTemplate />
</div>
<h4 className='mb-3 text-xl font-bold text-dark dark:text-white'>
{siteConfig('STARTER_FEATURE_2_TITLE_1')}
</h4>
<p className='mb-8 text-body-color dark:text-dark-6 lg:mb-9'>
{siteConfig('STARTER_FEATURE_2_TEXT_1')}
</p>
<Link
href={siteConfig('STARTER_FEATURE_2_BUTTON_URL', '')}
className='text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary'>
{siteConfig('STARTER_FEATURE_2_BUTTON_TEXT')}
</Link>
</div>
</div>
<div className='w-full px-4 md:w-1/2 lg:w-1/4'>
<div className='wow fadeInUp group mb-12' data-wow-delay='.2s'>
<div className='relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary'>
<span className='absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45'></span>
<SVGDesign />
</div>
<h4 className='mb-3 text-xl font-bold text-dark dark:text-white'>
{siteConfig('STARTER_FEATURE_3_TITLE_1')}
</h4>
<p className='mb-8 text-body-color dark:text-dark-6 lg:mb-9'>
{siteConfig('STARTER_FEATURE_3_TEXT_1')}
</p>
<Link
href={siteConfig('STARTER_FEATURE_3_BUTTON_URL', '')}
className='text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary'>
{siteConfig('STARTER_FEATURE_3_BUTTON_TEXT')}
</Link>
</div>
</div>
<div className='w-full px-4 md:w-1/2 lg:w-1/4'>
<div className='wow fadeInUp group mb-12' data-wow-delay='.25s'>
<div className='relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary'>
<span className='absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45'></span>
<SVGEssential />
</div>
<h4 className='mb-3 text-xl font-bold text-dark dark:text-white'>
{siteConfig('STARTER_FEATURE_4_TITLE_1')}
</h4>
<p className='mb-8 text-body-color dark:text-dark-6 lg:mb-9'>
{siteConfig('STARTER_FEATURE_4_TEXT_1')}
</p>
<Link
href={siteConfig('STARTER_FEATURE_4_BUTTON_URL', '')}
className='text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary'>
{siteConfig('STARTER_FEATURE_3_BUTTON_TEXT')}
</Link>
</div>
</div>
</div>
</div>
<div className="-mx-4 flex flex-wrap">
<div className="w-full px-4 md:w-1/2 lg:w-1/4">
<div className="wow fadeInUp group mb-12" data-wow-delay=".1s">
<div
className="relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary"
>
<span
className="absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45"
></span>
<SVGGifts/>
</div>
<h4 className="mb-3 text-xl font-bold text-dark dark:text-white">
{siteConfig('STARTER_FEATURE_1_TITLE_1', null, CONFIG)}
</h4>
<p className="mb-8 text-body-color dark:text-dark-6 lg:mb-9">
{siteConfig('STARTER_FEATURE_1_TEXT_1', null, CONFIG)}
</p>
<a
href={siteConfig('STARTER_FEATURE_1_BUTTON_URL', null, CONFIG)}
className="text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary"
>
{siteConfig('STARTER_FEATURE_1_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
<div className="w-full px-4 md:w-1/2 lg:w-1/4">
<div className="wow fadeInUp group mb-12" data-wow-delay=".15s">
<div
className="relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary"
>
<span
className="absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45"
></span>
<SVGTemplate/>
</div>
<h4 className="mb-3 text-xl font-bold text-dark dark:text-white">
{siteConfig('STARTER_FEATURE_2_TITLE_1', null, CONFIG)}
</h4>
<p className="mb-8 text-body-color dark:text-dark-6 lg:mb-9">
{siteConfig('STARTER_FEATURE_2_TEXT_1', null, CONFIG)}
</p>
<a
href={siteConfig('STARTER_FEATURE_2_BUTTON_URL', null, CONFIG)}
className="text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary"
>
{siteConfig('STARTER_FEATURE_2_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
<div className="w-full px-4 md:w-1/2 lg:w-1/4">
<div className="wow fadeInUp group mb-12" data-wow-delay=".2s">
<div
className="relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary"
>
<span
className="absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45"
></span>
<SVGDesign/>
</div>
<h4 className="mb-3 text-xl font-bold text-dark dark:text-white">
{siteConfig('STARTER_FEATURE_3_TITLE_1', null, CONFIG)}
</h4>
<p className="mb-8 text-body-color dark:text-dark-6 lg:mb-9">
{siteConfig('STARTER_FEATURE_3_TEXT_1', null, CONFIG)}
</p>
<a
href={siteConfig('STARTER_FEATURE_3_BUTTON_URL', null, CONFIG)}
className="text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary"
>
{siteConfig('STARTER_FEATURE_3_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
<div className="w-full px-4 md:w-1/2 lg:w-1/4">
<div className="wow fadeInUp group mb-12" data-wow-delay=".25s">
<div
className="relative z-10 mb-10 flex h-[70px] w-[70px] items-center justify-center rounded-[14px] bg-primary"
>
<span
className="absolute left-0 top-0 -z-[1] mb-8 flex h-[70px] w-[70px] rotate-[25deg] items-center justify-center rounded-[14px] bg-primary bg-opacity-20 duration-300 group-hover:rotate-45"
></span>
<SVGEssential/>
</div>
<h4 className="mb-3 text-xl font-bold text-dark dark:text-white">
{siteConfig('STARTER_FEATURE_4_TITLE_1', null, CONFIG)}
</h4>
<p className="mb-8 text-body-color dark:text-dark-6 lg:mb-9">
{siteConfig('STARTER_FEATURE_4_TEXT_1', null, CONFIG)}
</p>
<a
href={siteConfig('STARTER_FEATURE_4_BUTTON_URL', null, CONFIG)}
className="text-base font-medium text-dark hover:text-primary dark:text-white dark:hover:text-primary"
>
{siteConfig('STARTER_FEATURE_3_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
</div>
</div>
</section>
{/* <!-- ====== Features Section End --> */}
</section>
{/* <!-- ====== Features Section End --> */}
</>
)
}

View File

@@ -1,17 +1,16 @@
import { siteConfig } from '@/lib/config'
import SocialButton from '@/themes/fukasawa/components/SocialButton'
import CONFIG from '../config'
import { Logo } from './Logo'
import { SVGFooterCircleBG } from './svg/SVGFooterCircleBG'
import Link from 'next/link'
/* eslint-disable @next/next/no-img-element */
export const Footer = props => {
const latestPosts = props?.latestPosts ? props?.latestPosts.slice(0, 2) : []
const STARTER_FOOTER_LINK_GROUP = siteConfig(
'STARTER_FOOTER_LINK_GROUP',
[],
CONFIG
)
const footerPostCount = siteConfig('STARTER_FOOTER_POST_COUNT', 2)
const latestPosts = props?.latestPosts
? props?.latestPosts.slice(0, footerPostCount)
: []
const STARTER_FOOTER_LINK_GROUP = siteConfig('STARTER_FOOTER_LINK_GROUP', [])
return (
<>
{/* <!-- ====== Footer Section Start --> */}
@@ -26,7 +25,7 @@ export const Footer = props => {
<Logo white={true} />
</a>
<p className='mb-8 max-w-[270px] text-base text-gray-7'>
{siteConfig('STARTER_FOOTER_SLOGAN', null, CONFIG)}
{siteConfig('STARTER_FOOTER_SLOGAN')}
</p>
<div className='-mx-3 flex items-center'>
<div className='mx-3'>
@@ -50,11 +49,11 @@ export const Footer = props => {
{item?.LINK_GROUP?.map((l, i) => {
return (
<li key={i}>
<a
<Link
href={l.URL}
className='mb-3 inline-block text-base text-gray-7 hover:text-primary'>
{l.TITLE}
</a>
</Link>
</li>
)
})}
@@ -68,23 +67,28 @@ export const Footer = props => {
<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)}
{siteConfig('STARTER_FOOTER_BLOG_LATEST_TITLE')}
</h4>
{/* 展示两条最新博客文章 */}
<div className='flex flex-col gap-8'>
{latestPosts?.map((item, index) => {
return (
<a
<Link
key={index}
href={item?.href}
className='group flex items-center gap-[22px]'>
<div className='overflow-hidden rounded w-20 h-12'>
<img src={item.pageCoverThumbnail} alt={item.title} />
</div>
{item.pageCoverThumbnail && (
<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>
</Link>
)
})}
</div>
@@ -101,45 +105,27 @@ export const Footer = props => {
<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
<Link
href={siteConfig('STARTER_FOOTER_PRIVACY_POLICY_URL', '')}
className='px-3 text-base text-gray-7 hover:text-white hover:underline'>
{siteConfig('STARTER_FOOTER_PRIVACY_POLICY_TEXT')}
</Link>
<Link
href={siteConfig(
'STARTER_FOOTER_PRIVACY_POLICY_URL',
null,
CONFIG
'STARTER_FOOTER_PRIVACY_LEGAL_NOTICE_URL', ''
)}
className='px-3 text-base text-gray-7 hover:text-white hover:underline'>
{siteConfig('STARTER_FOOTER_PRIVACY_LEGAL_NOTICE_TEXT')}
</Link>
<Link
href={siteConfig(
'STARTER_FOOTER_PRIVACY_TERMS_OF_SERVICE_URL', ''
)}
className='px-3 text-base text-gray-7 hover:text-white hover:underline'>
{siteConfig(
'STARTER_FOOTER_PRIVACY_POLICY_TEXT',
null,
CONFIG
'STARTER_FOOTER_PRIVACY_TERMS_OF_SERVICE_TEXT', ''
)}
</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>
</Link>
</div>
</div>
</div>

View File

@@ -0,0 +1,117 @@
/* eslint-disable no-unreachable */
import DashboardButton from '@/components/ui/dashboard/DashboardButton'
import { siteConfig } from '@/lib/config'
import { useGlobal } from '@/lib/global'
import { SignedIn, SignedOut, UserButton } from '@clerk/nextjs'
import throttle from 'lodash.throttle'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useCallback, useEffect, useState } from 'react'
import { DarkModeButton } from './DarkModeButton'
import { Logo } from './Logo'
import { MenuList } from './MenuList'
/**
* 顶部导航栏
*/
export const Header = props => {
const router = useRouter()
const { isDarkMode } = useGlobal()
const [buttonTextColor, setColor] = useState(
router.route === '/' ? 'text-white' : ''
)
const enableClerk = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
useEffect(() => {
if (isDarkMode || router.route === '/') {
setColor('text-white')
} else {
setColor('')
}
// ======= Sticky
window.addEventListener('scroll', navBarScollListener)
return () => {
window.removeEventListener('scroll', navBarScollListener)
}
}, [isDarkMode])
// 滚动监听
const throttleMs = 200
const navBarScollListener = useCallback(
throttle(() => {
// eslint-disable-next-line camelcase
const ud_header = document.querySelector('.ud-header')
const scrollY = window.scrollY
// 控制台输出当前滚动位置和 sticky 值
if (scrollY > 0) {
ud_header?.classList?.add('sticky')
} else {
ud_header?.classList?.remove('sticky')
}
}, throttleMs)
)
return (
<>
{/* <!-- ====== Navbar Section Start --> */}
<div className='ud-header absolute left-0 top-0 z-40 flex w-full items-center bg-transparent'>
<div className='container'>
<div className='relative -mx-4 flex items-center justify-between'>
{/* Logo */}
<Logo {...props} />
<div className='flex w-full items-center justify-between px-4'>
{/* 中间菜单 */}
<MenuList {...props} />
{/* 右侧功能 */}
<div className='flex items-center gap-4 justify-end pr-16 lg:pr-0'>
{/* 深色模式切换 */}
<DarkModeButton />
{/* 注册登录功能 */}
{enableClerk && (
<>
<SignedOut>
<div className='hidden sm:flex gap-4'>
<Link
href={siteConfig('STARTER_NAV_BUTTON_1_URL', '')}
className={`loginBtn ${buttonTextColor} p-2 text-base font-medium hover:opacity-70`}>
{siteConfig('STARTER_NAV_BUTTON_1_TEXT')}
</Link>
<Link
href={siteConfig('STARTER_NAV_BUTTON_2_URL', '')}
className={`signUpBtn ${buttonTextColor} p-2 rounded-md bg-white bg-opacity-20 py-2 text-base font-medium duration-300 ease-in-out hover:bg-opacity-100 hover:text-dark`}>
{siteConfig('STARTER_NAV_BUTTON_2_TEXT')}
</Link>
</div>
</SignedOut>
<SignedIn>
<UserButton />
<DashboardButton className={'hidden md:block'} />
</SignedIn>
</>
)}
{!enableClerk && (
<div className='hidden sm:flex gap-4'>
<Link
href={siteConfig('STARTER_NAV_BUTTON_1_URL', '')}
className={`loginBtn ${buttonTextColor} p-2 text-base font-medium hover:opacity-70`}>
{siteConfig('STARTER_NAV_BUTTON_1_TEXT')}
</Link>
<Link
href={siteConfig('STARTER_NAV_BUTTON_2_URL', '')}
className={`signUpBtn ${buttonTextColor} p-2 rounded-md bg-white bg-opacity-20 py-2 text-base font-medium duration-300 ease-in-out hover:bg-opacity-100 hover:text-dark`}>
{siteConfig('STARTER_NAV_BUTTON_2_TEXT')}
</Link>
</div>
)}
</div>
</div>
</div>
</div>
</div>
{/* <!-- ====== Navbar Section End --> */}
</>
)
}

View File

@@ -1,96 +1,125 @@
/* eslint-disable @next/next/no-img-element */
import LazyImage from '@/components/LazyImage'
import { siteConfig } from '@/lib/config'
import CONFIG from '../config'
import Link from 'next/link'
/**
* 英雄大图区块
*/
export const Hero = () => {
return <>
{/* <!-- ====== Hero Section Start --> */}
<div
id="home"
className="relative overflow-hidden bg-primary pt-[120px] md:pt-[130px] lg:pt-[160px]"
>
<div className="container">
<div className="-mx-4 flex flex-wrap items-center">
<div className="w-full px-4">
<div
className="hero-content wow fadeInUp mx-auto max-w-[780px] text-center"
data-wow-delay=".2s"
>
{/* 主标题 */}
<h1
className="mb-6 text-3xl font-bold leading-snug text-white sm:text-4xl sm:leading-snug lg:text-5xl lg:leading-[1.2]"
>
{siteConfig('STARTER_HERO_TITLE_1', null, CONFIG)}
</h1>
{/* 次标题 */}
<p
className="mx-auto mb-9 max-w-[600px] text-base font-medium text-white sm:text-lg sm:leading-[1.44]"
>
{siteConfig('STARTER_HERO_TITLE_2', null, CONFIG)}
</p>
{/* 按钮组 */}
<ul
className="mb-10 flex flex-wrap items-center justify-center gap-5"
>
{siteConfig('STARTER_HERO_BUTTON_1_TEXT', null, CONFIG) &&
<li>
<a
href={siteConfig('STARTER_HERO_BUTTON_1_URL', null, CONFIG)}
className="inline-flex items-center justify-center rounded-md bg-white px-7 py-[14px] text-center text-base font-medium text-dark shadow-1 transition duration-300 ease-in-out hover:bg-gray-2 hover:text-body-color"
>
{siteConfig('STARTER_HERO_BUTTON_1_TEXT', null, CONFIG)}
</a>
</li>
}
{siteConfig('STARTER_HERO_BUTTON_2_TEXT', null, CONFIG) &&
<li>
<a
href={siteConfig('STARTER_HERO_BUTTON_2_URL', null, CONFIG)}
target="_blank"
className="flex items-center rounded-md bg-white/[0.12] px-6 py-[14px] text-base font-medium text-white transition duration-300 ease-in-out hover:bg-white hover:text-dark" rel="noreferrer"
>
{siteConfig('STARTER_HERO_BUTTON_2_ICON', null, CONFIG) && <img className='mr-4' src={siteConfig('STARTER_HERO_BUTTON_2_ICON', null, CONFIG)}/>}
{siteConfig('STARTER_HERO_BUTTON_2_TEXT', null, CONFIG)}
</a>
</li>
}
</ul>
</div>
</div>
{/* 产品预览图片 */}
{ siteConfig('STARTER_HERO_PREVIEW_IMAGE', null, CONFIG) && <div className="w-full px-4">
<div
className="wow fadeInUp relative z-10 mx-auto max-w-[845px]"
data-wow-delay=".25s"
>
<div className="mt-16">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={siteConfig('STARTER_HERO_PREVIEW_IMAGE', null, CONFIG)}
alt="hero"
className="mx-auto max-w-full rounded-t-xl rounded-tr-xl"
/>
</div>
{/* 背景图 */}
<div className="absolute -left-9 bottom-0 z-[-1]">
<img src='/images/starter/bg-hero-circle.svg'/>
</div>
<div className="absolute -right-6 -top-6 z-[-1]">
<img src='/images/starter/bg-hero-circle.svg'/>
export const Hero = props => {
const config = props?.NOTION_CONFIG || CONFIG
return (
<>
{/* <!-- ====== Hero Section Start --> */}
<div
id='home'
className='relative overflow-hidden bg-primary pt-[120px] md:pt-[130px] lg:pt-[160px]'>
<div className='container'>
<div className='-mx-4 flex flex-wrap items-center'>
<div className='w-full px-4'>
<div
className='hero-content wow fadeInUp mx-auto max-w-[780px] text-center'
data-wow-delay='.2s'>
{/* 主标题 */}
<h1 className='mb-6 text-3xl font-bold leading-snug text-white sm:text-4xl sm:leading-snug lg:text-5xl lg:leading-[1.2]'>
{siteConfig('STARTER_HERO_TITLE_1', null, config)}
</h1>
{/* 次标题 */}
<p className='mx-auto mb-9 max-w-[600px] text-base font-medium text-white sm:text-lg sm:leading-[1.44]'>
{siteConfig('STARTER_HERO_TITLE_2', null, config)}
</p>
{/* 按钮组 */}
<ul className='mb-10 flex flex-wrap items-center justify-center gap-5'>
{siteConfig('STARTER_HERO_BUTTON_1_TEXT', null, config) && (
<li>
<Link
href={siteConfig('STARTER_HERO_BUTTON_1_URL', '')}
className='inline-flex items-center justify-center rounded-md bg-white px-7 py-[14px] text-center text-base font-medium text-dark shadow-1 transition duration-300 ease-in-out hover:bg-gray-2 hover:text-body-color'>
{siteConfig('STARTER_HERO_BUTTON_1_TEXT', null, config)}
</Link>
</li>
)}
{siteConfig('STARTER_HERO_BUTTON_2_TEXT', null, config) && (
<li>
<Link
href={siteConfig(
'STARTER_HERO_BUTTON_2_URL',
null,
config
)}
target='_blank'
className='flex items-center rounded-md bg-white/[0.12] px-6 py-[14px] text-base font-medium text-white transition duration-300 ease-in-out hover:bg-white hover:text-dark'
rel='noreferrer'>
{siteConfig(
'STARTER_HERO_BUTTON_2_ICON',
null,
config
) && (
<img
className='mr-4'
src={siteConfig(
'STARTER_HERO_BUTTON_2_ICON',
null,
config
)}
/>
)}
{siteConfig('STARTER_HERO_BUTTON_2_TEXT', null, config)}
</Link>
</li>
)}
</ul>
</div>
</div>
</div>
}
{/* 产品预览图片 */}
{siteConfig('STARTER_HERO_PREVIEW_IMAGE', null, config) && (
<div className='w-full px-4'>
<div
className='wow fadeInUp relative z-10 mx-auto max-w-[845px]'
data-wow-delay='.25s'>
<div className='mt-16'>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={siteConfig(
'STARTER_HERO_PREVIEW_IMAGE',
null,
config
)}
alt={siteConfig('TITLE', null, config)}
title={siteConfig('TITLE', null, config)}
className='mx-auto max-w-full rounded-t-xl rounded-tr-xl'
/>
</div>
{/* 背景图 */}
<div className='absolute -left-9 bottom-0 z-[-1]'>
<img src='/images/starter/bg-hero-circle.svg' />
</div>
<div className='absolute -right-6 -top-6 z-[-1]'>
<img src='/images/starter/bg-hero-circle.svg' />
</div>
</div>
</div>
)}
</div>
</div>
</div>
</div>
{/* <!-- ====== Hero Section End --> */}
{/* 横幅图片 */}
{siteConfig('STARTER_HERO_BANNER_IMAGE', null, config) && (
<div className='container'>
<LazyImage
priority
className='w-full'
src={siteConfig(
'STARTER_HERO_BANNER_IMAGE',
null,
config
)}></LazyImage>
</div>
)}
{/* <!-- ====== Hero Section End --> */}
</>
)
}

View File

@@ -1,20 +1,22 @@
/* eslint-disable @next/next/no-img-element */
/* eslint-disable @next/next/no-html-link-for-pages */
import LazyImage from '@/components/LazyImage'
import { siteConfig } from '@/lib/config'
import { useGlobal } from '@/lib/global'
import throttle from 'lodash.throttle'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import CONFIG from '../config'
/**
* 站点图标
* @returns
*/
export const Logo = ({ white }) => {
export const Logo = props => {
const { white, NOTION_CONFIG } = props
const router = useRouter()
const logoWhite = siteConfig('STARTER_LOGO_WHITE')
const logoNormal = siteConfig('STARTER_LOGO')
const { isDarkMode } = useGlobal()
const logoWhite = siteConfig('STARTER_LOGO_WHITE', null, CONFIG)
const [logo, setLogo] = useState(logoWhite)
const [logoTextColor, setLogoTextColor] = useState('text-white')
@@ -25,11 +27,12 @@ export const Logo = ({ white }) => {
const scrollY = window.scrollY
// 何时显示浅色或白底的logo
const homePageNavBar = router.route === '/' && scrollY < 10 // 在首页并且视窗在页面顶部
if (white || isDarkMode || homePageNavBar) {
setLogo(siteConfig('STARTER_LOGO_WHITE', null, CONFIG))
setLogo(logoWhite)
setLogoTextColor('text-white')
} else {
setLogo(siteConfig('STARTER_LOGO', null, CONFIG))
setLogo(logoNormal)
setLogoTextColor('text-black')
}
}, throttleMs)
@@ -46,13 +49,14 @@ export const Logo = ({ white }) => {
<div className='navbar-logo flex items-center w-full py-5 cursor-pointer'>
{/* eslint-disable-next-line @next/next/no-img-element */}
{logo && (
<img
<LazyImage
priority
onClick={() => {
router.push('/')
}}
src={logo}
alt='logo'
className='header-logo w-full'
className='header-logo mr-1 h-8'
/>
)}
{/* logo文字 */}
@@ -60,7 +64,7 @@ export const Logo = ({ white }) => {
onClick={() => {
router.push('/')
}}
className={`${logoTextColor} dark:text-white py-1.5 header-logo-text whitespace-nowrap text-2xl font-semibold`}>
className={`${logoTextColor} logo dark:text-white py-1.5 header-logo-text whitespace-nowrap text-2xl font-semibold`}>
{siteConfig('TITLE')}
</span>
</div>

View File

@@ -1,31 +1,56 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState } from 'react'
/**
* 菜单链接
* @param {*} param0
* @returns
*/
export const MenuItem = ({ link }) => {
const hasSubMenu = link?.subMenus?.length > 0
const router = useRouter()
// 管理子菜单的展开状态
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false)
const toggleSubMenu = () => {
setIsSubMenuOpen(prev => !prev) // 切换子菜单状态
}
return (
<>
{/* MenuItem */}
{/* 普通 MenuItem */}
{!hasSubMenu && (
<li className='group relative whitespace-nowrap'>
<Link
href={link?.href}
target={link?.target}
className={`ud-menu-scroll mx-8 flex py-2 text-base font-medium text-dark group-hover:text-primary dark:text-white lg:mr-0 lg:inline-flex lg:px-0 lg:py-6 ${router.route === '/' ? 'lg:text-white lg:group-hover:text-white' : ''} lg:group-hover:opacity-70`}>
className={`ud-menu-scroll mx-8 flex py-2 text-base font-medium text-dark group-hover:text-primary dark:text-white lg:mr-0 lg:inline-flex lg:px-0 lg:py-6 ${
router.route === '/'
? 'lg:text-white lg:group-hover:text-white'
: ''
} lg:group-hover:opacity-70`}>
{link?.icon && <i className={link.icon + ' mr-2 my-auto'} />}
{link?.name}
</Link>
</li>
)}
{/* 有子菜单的 MenuItem */}
{hasSubMenu && (
<li className='submenu-item group relative whitespace-nowrap'>
{/* 有子菜单的MenuItem */}
<a
className={`relative mx-8 flex items-center justify-between py-2 text-base font-medium text-dark group-hover:text-primary dark:text-white lg:ml-8 lg:mr-0 lg:inline-flex lg:py-6 lg:pl-0 lg:pr-4 ${router.route === '/' ? 'lg:text-white lg:group-hover:text-white' : ''} lg:group-hover:opacity-70 xl:ml-10`}>
{link?.icon && <i className={link.icon + ' mr-2 my-auto'} />}
{link?.name}
<button
onClick={toggleSubMenu}
className={`cursor-pointer relative px-8 flex items-center justify-between py-2 text-base font-medium text-dark group-hover:text-primary dark:text-white lg:ml-8 lg:mr-0 lg:inline-flex lg:py-6 lg:pl-0 lg:pr-4 ${
router.route === '/'
? 'lg:text-white lg:group-hover:text-white'
: ''
} lg:group-hover:opacity-70 xl:ml-10`}>
<span>
{link?.icon && <i className={link.icon + ' mr-2 my-auto'} />}
{link?.name}
</span>
<svg
className='ml-2 fill-current'
@@ -36,26 +61,28 @@ export const MenuItem = ({ link }) => {
xmlns='http://www.w3.org/2000/svg'>
<path d='M7.99999 14.9C7.84999 14.9 7.72499 14.85 7.59999 14.75L1.84999 9.10005C1.62499 8.87505 1.62499 8.52505 1.84999 8.30005C2.07499 8.07505 2.42499 8.07505 2.64999 8.30005L7.99999 13.525L13.35 8.25005C13.575 8.02505 13.925 8.02505 14.15 8.25005C14.375 8.47505 14.375 8.82505 14.15 9.05005L8.39999 14.7C8.27499 14.825 8.14999 14.9 7.99999 14.9Z' />
</svg>
</a>
</button>
<div className='submenu relative left-0 top-full hidden w-[250px] rounded-sm bg-white p-4 transition-[top] duration-300 group-hover:opacity-100 dark:bg-dark-2 lg:invisible lg:absolute lg:top-[110%] lg:block lg:opacity-0 lg:shadow-lg lg:group-hover:visible lg:group-hover:top-full'>
{link.subMenus.map((sLink, index) => {
return (
<Link
key={index}
href={sLink.href}
target={link?.target}
className='block rounded px-4 py-[10px] text-sm text-body-color hover:text-primary dark:text-dark-6 dark:hover:text-primary'>
{/* 子菜单SubMenuItem */}
<span className='text-sm ml-4 whitespace-nowrap'>
{link?.icon && (
<i className={sLink.icon + ' mr-2 my-auto'} />
)}{' '}
{sLink.title}
</span>
</Link>
)
})}
{/* 子菜单 */}
<div
className={`submenu dark:border-gray-600 relative left-0 top-full w-[250px] rounded-sm bg-white p-4 transition-all duration-300 dark:bg-dark-2 lg:absolute lg:shadow-lg ${
isSubMenuOpen
? 'block opacity-100 visible'
: 'hidden opacity-0 invisible'
}`}>
{link.subMenus.map((sLink, index) => (
<Link
key={index}
href={sLink.href}
target={link?.target}
className='block rounded px-4 py-[10px] text-sm text-body-color hover:text-primary dark:text-dark-6 dark:hover:text-primary'>
{/* 子菜单 SubMenuItem */}
<span className='text-md ml-2 whitespace-nowrap'>
{link?.icon && <i className={sLink.icon + ' mr-2 my-auto'} />}{' '}
{sLink.title}
</span>
</Link>
))}
</div>
</li>
)}

View File

@@ -1,8 +1,10 @@
import BLOG from '@/blog.config'
import { siteConfig } from '@/lib/config'
import { useGlobal } from '@/lib/global'
import { useEffect } from 'react'
import CONFIG from '../config'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { MenuItem } from './MenuItem'
/**
* 响应式 折叠菜单
*/
@@ -10,30 +12,33 @@ export const MenuList = props => {
const { customNav, customMenu } = props
const { locale } = useGlobal()
const [showMenu, setShowMenu] = useState(false) // 控制菜单展开/收起状态
const router = useRouter()
let links = [
{
icon: 'fas fa-archive',
name: locale.NAV.ARCHIVE,
href: '/archive',
show: siteConfig('HEO_MENU_ARCHIVE', null, CONFIG)
show: siteConfig('HEO_MENU_ARCHIVE')
},
{
icon: 'fas fa-search',
name: locale.NAV.SEARCH,
href: '/search',
show: siteConfig('HEO_MENU_SEARCH', null, CONFIG)
show: siteConfig('HEO_MENU_SEARCH')
},
{
icon: 'fas fa-folder',
name: locale.COMMON.CATEGORY,
href: '/category',
show: siteConfig('HEO_MENU_CATEGORY', null, CONFIG)
show: siteConfig('HEO_MENU_CATEGORY')
},
{
icon: 'fas fa-tag',
name: locale.COMMON.TAGS,
href: '/tag',
show: siteConfig('HEO_MENU_TAG', null, CONFIG)
show: siteConfig('HEO_MENU_TAG')
}
]
@@ -41,68 +46,48 @@ export const MenuList = props => {
links = customNav.concat(links)
}
useEffect(() => {
// ===== responsive navbar
const navbarToggler = document.querySelector('#navbarToggler')
const navbarCollapse = document.querySelector('#navbarCollapse')
// 点击弹出菜单
navbarToggler?.addEventListener('click', () => {
navbarToggler?.classList.toggle('navbarTogglerActive')
navbarCollapse?.classList.toggle('hidden')
})
//= ==== close navbar-collapse when a clicked
document
.querySelectorAll('#navbarCollapse ul li:not(.submenu-item) a')
.forEach(e =>
e.addEventListener('click', () => {
navbarToggler?.classList.remove('navbarTogglerActive')
navbarCollapse?.classList.add('hidden')
})
)
// ===== Sub-menu
const submenuItems = document.querySelectorAll('.submenu-item')
submenuItems.forEach(el => {
el.querySelector('a')?.addEventListener('click', () => {
el.querySelector('.submenu')?.classList.toggle('hidden')
})
})
}, [])
// 如果 开启自定义菜单则覆盖Page生成的菜单
if (siteConfig('CUSTOM_MENU')) {
if (siteConfig('CUSTOM_MENU', BLOG.CUSTOM_MENU)) {
links = customMenu
}
// if (!links || links.length === 0) {
// return null
// }
if (!links || links.length === 0) {
return null
}
const toggleMenu = () => {
setShowMenu(!showMenu) // 切换菜单状态
}
useEffect(() => {
setShowMenu(false)
}, [router])
return (
<>
<div>
{/* 移动端菜单切换按钮 */}
<button
id='navbarToggler'
className='absolute right-4 top-1/2 block -translate-y-1/2 rounded-lg px-3 py-[6px] ring-primary focus:ring-2 lg:hidden'>
<span className='relative my-[6px] block h-[2px] w-[30px] bg-white duration-200 transition-all'></span>
<span className='relative my-[6px] block h-[2px] w-[30px] bg-white duration-200 transition-all'></span>
<span className='relative my-[6px] block h-[2px] w-[30px] bg-white duration-200 transition-all'></span>
</button>
<div>
{/* 移动端菜单切换按钮 */}
<button
id='navbarToggler'
onClick={toggleMenu}
className={`absolute right-4 top-1/2 block -translate-y-1/2 rounded-lg px-3 py-[6px] ring-primary focus:ring-2 lg:hidden ${
showMenu ? 'navbarTogglerActive' : ''
}`}>
<span className='relative my-[6px] block h-[2px] w-[30px] bg-white duration-200 transition-all'></span>
<span className='relative my-[6px] block h-[2px] w-[30px] bg-white duration-200 transition-all'></span>
<span className='relative my-[6px] block h-[2px] w-[30px] bg-white duration-200 transition-all'></span>
</button>
{/* 响应式菜单 */}
<nav
id='navbarCollapse'
className='absolute right-4 top-full hidden w-full max-w-[250px] rounded-lg bg-white py-5 shadow-lg dark:bg-dark-2 lg:static lg:block lg:w-full lg:max-w-full lg:bg-transparent lg:px-4 lg:py-0 lg:shadow-none dark:lg:bg-transparent xl:px-6'>
<ul className='blcok lg:flex 2xl:ml-20'>
{links?.map((link, index) => (
<MenuItem key={index} link={link} />
))}
</ul>
</nav>
</div>
</>
<nav
id='navbarCollapse'
className={`absolute right-4 top-full w-full max-w-[250px] rounded-lg bg-white py-5 shadow-lg dark:bg-dark-2 lg:static lg:block lg:w-full lg:max-w-full lg:bg-transparent lg:px-4 lg:py-0 lg:shadow-none dark:lg:bg-transparent xl:px-6 ${
showMenu ? '' : 'hidden'
}`}>
<ul className='blcok lg:flex 2xl:ml-20'>
{links?.map((link, index) => (
<MenuItem key={index} link={link} />
))}
</ul>
</nav>
</div>
)
}

View File

@@ -1,5 +1,4 @@
import { siteConfig } from '@/lib/config'
import CONFIG from '../config'
import { useRef, useState } from 'react'
/**
@@ -16,7 +15,7 @@ export const MessageForm = () => {
message: ''
})
const handleChange = (e) => {
const handleChange = e => {
const { name, value } = e.target
setFormData(prevState => ({
...prevState,
@@ -24,89 +23,90 @@ export const MessageForm = () => {
}))
}
return <>
<h3
className="mb-8 text-2xl font-semibold text-dark dark:text-white md:text-[28px] md:leading-[1.42]"
>
{siteConfig('STARTER_CONTACT_MSG_TITLE', null, CONFIG)}
</h3>
<form ref={formRef}>
<div className="mb-[22px]">
<label
// for="fullName"
className="mb-4 block text-sm text-body-color dark:text-dark-6">
{siteConfig('STARTER_CONTACT_MSG_NAME', null, CONFIG)}*
</label>
<input
disabled={success}
type="text"
name="fullName"
value={formData.fullName}
onChange={handleChange}
placeholder="Adam Gelius"
className="w-full border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6"
/>
</div>
<div className="mb-[22px]">
<label
// for="email"
className="mb-4 block text-sm text-body-color dark:text-dark-6">
{siteConfig('STARTER_CONTACT_MSG_EMAIL', null, CONFIG)}*
</label >
<input
disabled={success}
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="example@yourmail.com"
className="w-full border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6"
/>
</div>
<div className="mb-[22px]">
<label
// for="phone"
className="mb-4 block text-sm text-body-color dark:text-dark-6">
{siteConfig('STARTER_CONTACT_MSG_PHONE', null, CONFIG)}*
</label >
<input
disabled={success}
type="text"
name="phone"
value={formData.phone}
onChange={handleChange}
placeholder="+885 1254 5211 552"
className="w-full border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6"
/>
</div>
<div className="mb-[30px]">
<label
// for="message"
className="mb-4 block text-sm text-body-color dark:text-dark-6">
{siteConfig('STARTER_CONTACT_MSG_TEXT', null, CONFIG)}*
</label >
<textarea
disabled={success}
name="message"
value={formData.message}
onChange={handleChange}
rows="1"
placeholder="type your message here"
className="w-full resize-none border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6"
></textarea>
</div>
<div className="mb-0">
<button
disabled={success}
type="submit"
className="inline-flex items-center justify-center rounded-md bg-primary px-10 py-3 text-base font-medium text-white transition duration-300 ease-in-out hover:bg-blue-dark"
>
{siteConfig('STARTER_CONTACT_MSG_SEND', null, CONFIG)}
</button>
{/* Success message */}
{success && <p className="mt-2 text-green-600 text-sm">{siteConfig('STARTER_CONTACT_MSG_THANKS', null, CONFIG)}</p>}
</div>
</form>
</>
return (
<>
<h3 className='mb-8 text-2xl font-semibold text-dark dark:text-white md:text-[28px] md:leading-[1.42]'>
{siteConfig('STARTER_CONTACT_MSG_TITLE')}
</h3>
<form ref={formRef}>
<div className='mb-[22px]'>
<label
// for="fullName"
className='mb-4 block text-sm text-body-color dark:text-dark-6'>
{siteConfig('STARTER_CONTACT_MSG_NAME')}*
</label>
<input
disabled={success}
type='text'
name='fullName'
value={formData.fullName}
onChange={handleChange}
placeholder='Adam Gelius'
className='w-full border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6'
/>
</div>
<div className='mb-[22px]'>
<label
// for="email"
className='mb-4 block text-sm text-body-color dark:text-dark-6'>
{siteConfig('STARTER_CONTACT_MSG_EMAIL')}*
</label>
<input
disabled={success}
type='email'
name='email'
value={formData.email}
onChange={handleChange}
placeholder='example@yourmail.com'
className='w-full border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6'
/>
</div>
<div className='mb-[22px]'>
<label
// for="phone"
className='mb-4 block text-sm text-body-color dark:text-dark-6'>
{siteConfig('STARTER_CONTACT_MSG_PHONE')}*
</label>
<input
disabled={success}
type='text'
name='phone'
value={formData.phone}
onChange={handleChange}
placeholder='+885 1254 5211 552'
className='w-full border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6'
/>
</div>
<div className='mb-[30px]'>
<label
// for="message"
className='mb-4 block text-sm text-body-color dark:text-dark-6'>
{siteConfig('STARTER_CONTACT_MSG_TEXT')}*
</label>
<textarea
disabled={success}
name='message'
value={formData.message}
onChange={handleChange}
rows='1'
placeholder='type your message here'
className='w-full resize-none border-0 border-b border-[#f1f1f1] bg-transparent pb-3 text-body-color placeholder:text-body-color/60 focus:border-primary focus:outline-none dark:border-dark-3 dark:text-dark-6'></textarea>
</div>
<div className='mb-0'>
<button
disabled={success}
type='submit'
className='inline-flex items-center justify-center rounded-md bg-primary px-10 py-3 text-base font-medium text-white transition duration-300 ease-in-out hover:bg-blue-dark'>
{siteConfig('STARTER_CONTACT_MSG_SEND')}
</button>
{/* Success message */}
{success && (
<p className='mt-2 text-green-600 text-sm'>
{siteConfig('STARTER_CONTACT_MSG_THANKS')}
</p>
)}
</div>
</form>
</>
)
}

View File

@@ -1,91 +0,0 @@
/* eslint-disable no-unreachable */
import throttle from 'lodash.throttle';
import { useCallback, useEffect, useState } from 'react'
import { MenuList } from './MenuList';
import { DarkModeButton } from './DarkModeButton';
import { Logo } from './Logo';
import { useRouter } from 'next/router';
import { siteConfig } from '@/lib/config';
import CONFIG from '../config';
import { useGlobal } from '@/lib/global';
/**
* 顶部导航栏
*/
export const NavBar = (props) => {
const router = useRouter()
const { isDarkMode } = useGlobal()
const [buttonTextColor, setColor] = useState(router.route === '/' ? 'text-white' : '')
useEffect(() => {
if (isDarkMode || router.route === '/') {
setColor('text-white')
} else {
setColor('')
}
// ======= Sticky
window.addEventListener('scroll', navBarScollListener)
return () => {
window.removeEventListener('scroll', navBarScollListener)
}
}, [[isDarkMode]])
// 滚动监听
const throttleMs = 200
const navBarScollListener = useCallback(
throttle(() => {
// eslint-disable-next-line camelcase
const ud_header = document.querySelector('.ud-header');
const scrollY = window.scrollY;
// 控制台输出当前滚动位置和 sticky 值
if (scrollY > 0) {
ud_header?.classList?.add('sticky');
} else {
ud_header?.classList?.remove('sticky');
}
}, throttleMs)
)
return <>
{/* <!-- ====== Navbar Section Start --> */}
<div className="ud-header absolute left-0 top-0 z-40 flex w-full items-center bg-transparent" >
<div className="container">
<div className="relative -mx-4 flex items-center justify-between">
{/* Logo */}
<Logo/>
<div className="flex w-full items-center justify-between px-4">
{/* 中间菜单 */}
<MenuList {...props}/>
{/* 右侧功能 */}
<div className="flex items-center justify-end pr-16 lg:pr-0">
{/* 深色模式切换 */}
<DarkModeButton/>
{/* 注册登录功能 */}
<div className="hidden sm:flex">
<a
href={siteConfig('STARTER_NAV_BUTTON_1_URL', null, CONFIG)}
className={`loginBtn ${buttonTextColor} px-[22px] py-2 text-base font-medium hover:opacity-70`}
>
{siteConfig('STARTER_NAV_BUTTON_1_TEXT', null, CONFIG)}
</a>
<a
href={siteConfig('STARTER_NAV_BUTTON_2_URL', null, CONFIG)}
className={`signUpBtn ${buttonTextColor} rounded-md bg-white bg-opacity-20 px-6 py-2 text-base font-medium duration-300 ease-in-out hover:bg-opacity-100 hover:text-dark`}
>
{siteConfig('STARTER_NAV_BUTTON_2_TEXT', null, CONFIG)}
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{/* <!-- ====== Navbar Section End --> */}
</>
}

View File

@@ -1,178 +1,178 @@
import { siteConfig } from '@/lib/config'
import CONFIG from '../config'
import Link from 'next/link'
/**
* 价格板块
* @returns
*/
export const Pricing = () => {
return <>
{/* <!-- ====== Pricing Section Start --> */}
<section
id="pricing"
className="relative z-20 overflow-hidden bg-white pb-12 pt-20 dark:bg-dark 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-[510px] text-center">
<span className="mb-2 block text-lg font-semibold text-primary">
{siteConfig('STARTER_PRICING_TITLE', null, CONFIG)}
</span>
<h2
className="mb-3 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]"
>
{siteConfig('STARTER_PRICING_TEXT_1', null, CONFIG)}
</h2>
<p className="text-base text-body-color dark:text-dark-6">
{siteConfig('STARTER_PRICING_TEXT_2', null, CONFIG)}
</p>
return (
<>
{/* <!-- ====== Pricing Section Start --> */}
<section
id='pricing'
className='relative overflow-hidden bg-white pb-12 pt-20 dark:bg-dark 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-[510px] text-center'>
<span className='mb-2 block text-lg font-semibold text-primary'>
{siteConfig('STARTER_PRICING_TITLE')}
</span>
<h2 className='mb-3 text-3xl font-bold text-dark dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.2]'>
{siteConfig('STARTER_PRICING_TEXT_1')}
</h2>
<p className='text-base text-body-color dark:text-dark-6'>
{siteConfig('STARTER_PRICING_TEXT_2')}
</p>
</div>
</div>
</div>
<div className='-mx-4 flex flex-wrap justify-center'>
{/* 第一个付费计划 */}
<div className='w-full px-4 md:w-1/2 lg:w-1/3'>
<div className='relative z-10 mb-10 overflow-hidden rounded-xl bg-white px-8 py-10 shadow-pricing dark:bg-dark-2 sm:p-12 lg:px-6 lg:py-10 xl:p-14'>
<span className='mb-5 block text-xl font-medium text-dark dark:text-white'>
{siteConfig('STARTER_PRICING_1_TITLE')}
</span>
<h2 className='space-x-1 mb-11 text-4xl font-semibold text-dark dark:text-white xl:text-[42px] xl:leading-[1.21]'>
<span className='text-xl font-medium'>
{siteConfig('STARTER_PRICING_1_PRICE_CURRENCY')}
</span>
<span className='-ml-1 -tracking-[2px]'>
{siteConfig('STARTER_PRICING_1_PRICE')}
</span>
<span className='text-base font-normal text-body-color dark:text-dark-6'>
{siteConfig('STARTER_PRICING_1_PRICE_PERIOD')}
</span>
</h2>
<div className='mb-[50px]'>
<h5 className='mb-5 text-lg font-medium text-dark dark:text-white'>
{siteConfig('STARTER_PRICING_1_HEADER')}
</h5>
<div className='flex flex-col gap-[14px]'>
{siteConfig('STARTER_PRICING_1_FEATURES')
?.split(',')
.map((feature, index) => {
return (
<p
key={index}
className='text-base text-body-color dark:text-dark-6'>
{feature}
</p>
)
})}
</div>
</div>
<Link
href={siteConfig('STARTER_PRICING_1_BUTTON_URL', '')}
className='inline-block rounded-md bg-primary px-7 py-3 text-center text-base font-medium text-white transition hover:bg-blue-dark'>
{siteConfig('STARTER_PRICING_1_BUTTON_TEXT')}
</Link>
</div>
</div>
{/* 第二个付费计划 */}
<div className='w-full px-4 md:w-1/2 lg:w-1/3'>
<div className='relative z-10 mb-10 overflow-hidden rounded-xl bg-white px-8 py-10 shadow-pricing dark:bg-dark-2 sm:p-12 lg:px-6 lg:py-10 xl:p-14'>
<p
style={{
writingMode: 'vertical-rl',
textOrientation: 'mixed'
}}
className='absolute p-1 right-0 top-0 inline-block rounded-bl-md rounded-tl-md bg-primary text-base font-medium text-white tracking-wider'>
{siteConfig('STARTER_PRICING_2_TAG')}
</p>
<span className='mb-5 block text-xl font-medium text-dark dark:text-white'>
{siteConfig('STARTER_PRICING_2_TITLE')}
</span>
<h2 className='space-x-1 mb-11 text-4xl font-semibold text-dark dark:text-white xl:text-[42px] xl:leading-[1.21]'>
<span className='text-xl font-medium'>
{siteConfig('STARTER_PRICING_2_PRICE_CURRENCY')}
</span>
<span className='-ml-1 -tracking-[2px]'>
{siteConfig('STARTER_PRICING_2_PRICE')}
</span>
<span className='text-base font-normal text-body-color dark:text-dark-6'>
{siteConfig('STARTER_PRICING_2_PRICE_PERIOD')}
</span>
</h2>
<div className='mb-[50px]'>
<h5 className='mb-5 text-lg font-medium text-dark dark:text-white'>
{siteConfig('STARTER_PRICING_2_HEADER')}
</h5>
<div className='flex flex-col gap-[14px]'>
{siteConfig('STARTER_PRICING_2_FEATURES')
?.split(',')
.map((feature, index) => {
return (
<p
key={index}
className='text-base text-body-color dark:text-dark-6'>
{feature}
</p>
)
})}
</div>
</div>
<Link
href={siteConfig('STARTER_PRICING_2_BUTTON_URL', '')}
className='inline-block rounded-md bg-primary px-7 py-3 text-center text-base font-medium text-white transition hover:bg-blue-dark'>
{siteConfig('STARTER_PRICING_2_BUTTON_TEXT')}
</Link>
</div>
</div>
{/* 第三个付费计划 */}
<div className='w-full px-4 md:w-1/2 lg:w-1/3'>
<div className='relative z-10 mb-10 overflow-hidden rounded-xl bg-white px-8 py-10 shadow-pricing dark:bg-dark-2 sm:p-12 lg:px-6 lg:py-10 xl:p-14'>
<span className='mb-5 block text-xl font-medium text-dark dark:text-white'>
{siteConfig('STARTER_PRICING_3_TITLE')}
</span>
<h2 className='space-x-1 mb-11 text-4xl font-semibold text-dark dark:text-white xl:text-[42px] xl:leading-[1.21]'>
<span className='text-xl font-medium'>
{siteConfig('STARTER_PRICING_3_PRICE_CURRENCY')}
</span>
<span className='-ml-1 -tracking-[2px]'>
{siteConfig('STARTER_PRICING_3_PRICE')}
</span>
<span className='text-base font-normal text-body-color dark:text-dark-6'>
{siteConfig('STARTER_PRICING_3_PRICE_PERIOD')}
</span>
</h2>
<div className='mb-[50px]'>
<h5 className='mb-5 text-lg font-medium text-dark dark:text-white'>
{siteConfig('STARTER_PRICING_3_HEADER')}
</h5>
<div className='flex flex-col gap-[14px]'>
{siteConfig('STARTER_PRICING_3_FEATURES')
?.split(',')
.map((feature, index) => {
return (
<p
key={index}
className='text-base text-body-color dark:text-dark-6'>
{feature}
</p>
)
})}
</div>
</div>
<Link
href={siteConfig('STARTER_PRICING_3_BUTTON_URL', '')}
className='inline-block rounded-md bg-primary px-7 py-3 text-center text-base font-medium text-white transition hover:bg-blue-dark'>
{siteConfig('STARTER_PRICING_3_BUTTON_TEXT')}
</Link>
</div>
</div>
</div>
</div>
<div className="-mx-4 flex flex-wrap justify-center">
{/* 第一个付费计划 */}
<div className="w-full px-4 md:w-1/2 lg:w-1/3">
<div
className="relative z-10 mb-10 overflow-hidden rounded-xl bg-white px-8 py-10 shadow-pricing dark:bg-dark-2 sm:p-12 lg:px-6 lg:py-10 xl:p-14"
>
<span
className="mb-5 block text-xl font-medium text-dark dark:text-white"
>
{siteConfig('STARTER_PRICING_1_TITLE', null, CONFIG)}
</span>
<h2
className="space-x-1 mb-11 text-4xl font-semibold text-dark dark:text-white xl:text-[42px] xl:leading-[1.21]"
>
<span className="text-xl font-medium">{siteConfig('STARTER_PRICING_1_PRICE_CURRENCY', null, CONFIG)}</span>
<span className="-ml-1 -tracking-[2px]">{siteConfig('STARTER_PRICING_1_PRICE', null, CONFIG)}</span>
<span
className="text-base font-normal text-body-color dark:text-dark-6"
>
{siteConfig('STARTER_PRICING_1_PRICE_PERIOD', null, CONFIG)}
</span>
</h2>
<div className="mb-[50px]">
<h5 className="mb-5 text-lg font-medium text-dark dark:text-white">
{siteConfig('STARTER_PRICING_1_HEADER', null, CONFIG)}
</h5>
<div className="flex flex-col gap-[14px]">
{siteConfig('STARTER_PRICING_1_FEATURES', null, CONFIG)?.split(',').map((feature, index) => {
return <p key={index} className="text-base text-body-color dark:text-dark-6">
{feature}
</p>
})}
</div>
</div>
<a
href={siteConfig('STARTER_PRICING_1_BUTTON_URL', null, CONFIG)}
className="inline-block rounded-md bg-primary px-7 py-3 text-center text-base font-medium text-white transition hover:bg-blue-dark"
>
{siteConfig('STARTER_PRICING_1_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
{/* 第二个付费计划 */}
<div className="w-full px-4 md:w-1/2 lg:w-1/3">
<div
className="relative z-10 mb-10 overflow-hidden rounded-xl bg-white px-8 py-10 shadow-pricing dark:bg-dark-2 sm:p-12 lg:px-6 lg:py-10 xl:p-14"
>
<p style={{ writingMode: 'vertical-rl', textOrientation: 'mixed' }}
className="absolute p-1 right-0 top-0 inline-block rounded-bl-md rounded-tl-md bg-primary text-base font-medium text-white tracking-wider"
>
{siteConfig('STARTER_PRICING_2_TAG', null, CONFIG)}
</p>
<span
className="mb-5 block text-xl font-medium text-dark dark:text-white"
>
{siteConfig('STARTER_PRICING_2_TITLE', null, CONFIG)}
</span>
<h2
className="space-x-1 mb-11 text-4xl font-semibold text-dark dark:text-white xl:text-[42px] xl:leading-[1.21]"
>
<span className="text-xl font-medium">{siteConfig('STARTER_PRICING_2_PRICE_CURRENCY', null, CONFIG)}</span>
<span className="-ml-1 -tracking-[2px]">{siteConfig('STARTER_PRICING_2_PRICE', null, CONFIG)}</span>
<span
className="text-base font-normal text-body-color dark:text-dark-6"
>
{siteConfig('STARTER_PRICING_2_PRICE_PERIOD', null, CONFIG)}
</span>
</h2>
<div className="mb-[50px]">
<h5 className="mb-5 text-lg font-medium text-dark dark:text-white">
{siteConfig('STARTER_PRICING_2_HEADER', null, CONFIG)}
</h5>
<div className="flex flex-col gap-[14px]">
{siteConfig('STARTER_PRICING_2_FEATURES', null, CONFIG)?.split(',').map((feature, index) => {
return <p key={index} className="text-base text-body-color dark:text-dark-6">
{feature}
</p>
})}
</div>
</div>
<a
href={siteConfig('STARTER_PRICING_2_BUTTON_URL', null, CONFIG)}
className="inline-block rounded-md bg-primary px-7 py-3 text-center text-base font-medium text-white transition hover:bg-blue-dark"
>
{siteConfig('STARTER_PRICING_2_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
{/* 第三个付费计划 */}
<div className="w-full px-4 md:w-1/2 lg:w-1/3">
<div
className="relative z-10 mb-10 overflow-hidden rounded-xl bg-white px-8 py-10 shadow-pricing dark:bg-dark-2 sm:p-12 lg:px-6 lg:py-10 xl:p-14"
>
<span
className="mb-5 block text-xl font-medium text-dark dark:text-white"
>
{siteConfig('STARTER_PRICING_3_TITLE', null, CONFIG)}
</span>
<h2
className="space-x-1 mb-11 text-4xl font-semibold text-dark dark:text-white xl:text-[42px] xl:leading-[1.21]"
>
<span className="text-xl font-medium">{siteConfig('STARTER_PRICING_3_PRICE_CURRENCY', null, CONFIG)}</span>
<span className="-ml-1 -tracking-[2px]">{siteConfig('STARTER_PRICING_3_PRICE', null, CONFIG)}</span>
<span
className="text-base font-normal text-body-color dark:text-dark-6"
>
{siteConfig('STARTER_PRICING_3_PRICE_PERIOD', null, CONFIG)}
</span>
</h2>
<div className="mb-[50px]">
<h5 className="mb-5 text-lg font-medium text-dark dark:text-white">
{siteConfig('STARTER_PRICING_3_HEADER', null, CONFIG)}
</h5>
<div className="flex flex-col gap-[14px]">
{siteConfig('STARTER_PRICING_3_FEATURES', null, CONFIG)?.split(',').map((feature, index) => {
return <p key={index} className="text-base text-body-color dark:text-dark-6">
{feature}
</p>
})}
</div>
</div>
<a
href={siteConfig('STARTER_PRICING_3_BUTTON_URL', null, CONFIG)}
className="inline-block rounded-md bg-primary px-7 py-3 text-center text-base font-medium text-white transition hover:bg-blue-dark"
>
{siteConfig('STARTER_PRICING_3_BUTTON_TEXT', null, CONFIG)}
</a>
</div>
</div>
</div>
</div>
</section>
{/* <!-- ====== Pricing Section End --> */}
</>
</section>
{/* <!-- ====== Pricing Section End --> */}
</>
)
}

View File

@@ -0,0 +1,107 @@
import { useGlobal } from '@/lib/global'
import { useRouter } from 'next/router'
import { useImperativeHandle, useRef, useState } from 'react'
let lock = false
/**
* 搜索输入框
* @param {*} param0
* @returns
*/
const SearchInput = ({ currentTag, keyword, cRef }) => {
const { locale } = useGlobal()
const router = useRouter()
const searchInputRef = useRef(null)
useImperativeHandle(cRef, () => {
return {
focus: () => {
searchInputRef?.current?.focus()
}
}
})
const handleSearch = () => {
const key = searchInputRef.current.value
if (key && key !== '') {
router.push({ pathname: '/search/' + key }).then(r => {})
} else {
router.push({ pathname: '/' }).then(r => {})
}
}
const handleKeyUp = e => {
if (e.keyCode === 13) {
// 回车
handleSearch(searchInputRef.current.value)
} else if (e.keyCode === 27) {
// ESC
cleanSearch()
}
}
const cleanSearch = () => {
searchInputRef.current.value = ''
setShowClean(false)
}
function lockSearchInput() {
lock = true
}
function unLockSearchInput() {
lock = false
}
const [showClean, setShowClean] = useState(false)
const updateSearchKey = val => {
if (lock) {
return
}
searchInputRef.current.value = val
if (val) {
setShowClean(true)
} else {
setShowClean(false)
}
}
return (
<section className='flex w-full bg-gray-100'>
<input
ref={searchInputRef}
type='text'
placeholder={
currentTag
? `${locale.SEARCH.TAGS} #${currentTag}`
: `${locale.SEARCH.ARTICLES}`
}
className={
'outline-none w-full text-sm pl-4 transition focus:shadow-lg font-light leading-10 text-black bg-gray-100 dark:bg-gray-900 dark:text-white'
}
onKeyUp={handleKeyUp}
onCompositionStart={lockSearchInput}
onCompositionUpdate={lockSearchInput}
onCompositionEnd={unLockSearchInput}
onChange={e => updateSearchKey(e.target.value)}
defaultValue={keyword || ''}
/>
<div
className='-ml-8 cursor-pointer float-right items-center justify-center py-2'
onClick={handleSearch}>
<i
className={
'hover:text-black transform duration-200 text-gray-500 cursor-pointer fas fa-search'
}
/>
</div>
{showClean && (
<div className='-ml-12 cursor-pointer dark:bg-gray-600 dark:hover:bg-gray-800 float-right items-center justify-center py-2'>
<i
className='hover:text-black transform duration-200 text-gray-400 cursor-pointer fas fa-times'
onClick={cleanSearch}
/>
</div>
)}
</section>
)
}
export default SearchInput

View File

@@ -1,9 +1,9 @@
/* eslint-disable @next/next/no-img-element */
import { siteConfig } from '@/lib/config'
import CONFIG from '../config'
import { SVGAvatarBG } from './svg/SVGAvatarBG'
export const Team = () => {
const STARTER_TEAM_ITEMS = siteConfig('STARTER_TEAM_ITEMS', [])
return (
<>
{/* <!-- ====== Team Section Start --> */}
@@ -15,14 +15,14 @@ export const Team = () => {
<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)}
{siteConfig('STARTER_TEAM_TITLE')}
</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)}
{siteConfig('STARTER_TEAM_TEXT_1')}
</h2>
<p
dangerouslySetInnerHTML={{
__html: siteConfig('STARTER_TEAM_TEXT_2', null, CONFIG)
__html: siteConfig('STARTER_TEAM_TEXT_2')
}}
className='text-base text-body-color dark:text-dark-6'></p>
</div>
@@ -31,7 +31,7 @@ export const Team = () => {
{/* 团队成员排列矩阵 */}
<div className='-mx-4 flex flex-wrap justify-center'>
{CONFIG.STARTER_TEAM_ITEMS.map((item, index) => {
{STARTER_TEAM_ITEMS?.map((item, index) => {
return (
<div
key={index}

View File

@@ -4,7 +4,6 @@
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'
@@ -60,11 +59,7 @@ export const Testimonials = () => {
}, [])
// 用户评分
const ratings = [1, 2, 3, 4, 5]
const STARTER_TESTIMONIALS_ITEMS = siteConfig(
'STARTER_TESTIMONIALS_ITEMS',
[],
CONFIG
)
const STARTER_TESTIMONIALS_ITEMS = siteConfig('STARTER_TESTIMONIALS_ITEMS')
return (
<>
{/* <!-- ====== Testimonial Section Start --> */}
@@ -76,13 +71,13 @@ export const Testimonials = () => {
<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)}
{siteConfig('STARTER_TESTIMONIALS_TITLE')}
</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)}
{siteConfig('STARTER_TESTIMONIALS_TEXT_1')}
</h2>
<p className='text-base text-body-color dark:text-dark-6'>
{siteConfig('STARTER_TESTIMONIALS_TEXT_2', null, CONFIG)}
{siteConfig('STARTER_TESTIMONIALS_TEXT_2')}
</p>
</div>
</div>
@@ -92,7 +87,7 @@ export const Testimonials = () => {
<div className='swiper testimonial-carousel common-carousel p-5'>
<div className='swiper-wrapper'>
{/* 用户评价卡牌 */}
{STARTER_TESTIMONIALS_ITEMS.map((item, index) => {
{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]'>
@@ -101,11 +96,7 @@ export const Testimonials = () => {
<img
key={index}
alt='star icon' // 为每个图片设置唯一的 key 属性
src={siteConfig(
'STARTER_TESTIMONIALS_STAR_ICON',
null,
CONFIG
)}
src={siteConfig('STARTER_TESTIMONIALS_STAR_ICON')}
/>
))}
</div>