Skip to content

Commit

Permalink
Merge pull request #2216 from tangly1024/feat/theme-commerce
Browse files Browse the repository at this point in the history
Feat/theme commerce
  • Loading branch information
tangly1024 committed Mar 24, 2024
2 parents 89dbf49 + c255122 commit 7fc3063
Show file tree
Hide file tree
Showing 56 changed files with 2,825 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .env.local
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
NEXT_PUBLIC_VERSION=4.4.1
NEXT_PUBLIC_VERSION=4.4.2


# 可在此添加环境变量,去掉最左边的(# )注释即可
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "notion-next",
"version": "4.4.1",
"version": "4.4.2",
"homepage": "https://github.com/tangly1024/NotionNext.git",
"license": "MIT",
"repository": {
Expand Down
30 changes: 30 additions & 0 deletions themes/commerce/components/AnalyticsCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Card from './Card'

export function AnalyticsCard (props) {
const { postCount } = props
return <Card>
<div className='ml-2 mb-3 '>
<i className='fas fa-chart-area' /> 统计
</div>
<div className='text-xs font-light justify-center mx-7'>
<div className='inline'>
<div className='flex justify-between'>
<div>文章数:</div>
<div>{postCount}</div>
</div>
</div>
<div className='hidden busuanzi_container_page_pv ml-2'>
<div className='flex justify-between'>
<div>访问量:</div>
<div className='busuanzi_value_page_pv' />
</div>
</div>
<div className='hidden busuanzi_container_site_uv ml-2'>
<div className='flex justify-between'>
<div>访客数:</div>
<div className='busuanzi_value_site_uv' />
</div>
</div>
</div>
</Card>
}
21 changes: 21 additions & 0 deletions themes/commerce/components/Announcement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useGlobal } from '@/lib/global'
import dynamic from 'next/dynamic'

const NotionPage = dynamic(() => import('@/components/NotionPage'))

const Announcement = ({ post, className }) => {
const { locale } = useGlobal()
if (post?.blockMap) {
return <div className={className}>
<section id='announcement-wrapper' className="dark:text-gray-300 border dark:border-black rounded-xl lg:p-6 p-4 bg-white dark:bg-hexo-black-gray">
<div><i className='mr-2 fas fa-bullhorn' />{locale.COMMON.ANNOUNCEMENT}</div>
{post && (<div id="announcement-content">
<NotionPage post={post} className='text-center' />
</div>)}
</section>
</div>
} else {
return <></>
}
}
export default Announcement
33 changes: 33 additions & 0 deletions themes/commerce/components/ArticleAdjacent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Link from 'next/link'
import CONFIG from '../config'

/**
* 上一篇,下一篇文章
* @param {prev,next} param0
* @returns
*/
export default function ArticleAdjacent ({ prev, next }) {
if (!prev || !next || !CONFIG.ARTICLE_ADJACENT) {
return <></>
}
return (
<section className='pt-8 text-gray-800 items-center text-xs md:text-sm flex justify-between m-1 '>
<Link
href={`/${prev.slug}`}
passHref
className='py-1 cursor-pointer hover:underline justify-start items-center dark:text-white flex w-full h-full duration-200'>

<i className='mr-1 fas fa-angle-left' />{prev.title}

</Link>
<Link
href={`/${next.slug}`}
passHref
className='py-1 cursor-pointer hover:underline justify-end items-center dark:text-white flex w-full h-full duration-200'>
{next.title}
<i className='ml-1 my-1 fas fa-angle-right' />

</Link>
</section>
)
}
43 changes: 43 additions & 0 deletions themes/commerce/components/ArticleCopyright.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import CONFIG from '../config'
import { siteConfig } from '@/lib/config'

export default function ArticleCopyright () {
const router = useRouter()
const [path, setPath] = useState(siteConfig('LINK') + router.asPath)
useEffect(() => {
setPath(window.location.href)
})

const { locale } = useGlobal()

if (!CONFIG.ARTICLE_COPYRIGHT) {
return <></>
}

return (
<section className="dark:text-gray-300 mt-6 mx-1 ">
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-900 bg-gray-100 p-5 leading-8 border-l-2 border-red-500">
<li>
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
<Link href={'/about'} className="hover:underline">
{siteConfig('AUTHOR')}
</Link>
</li>
<li>
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
<a className="whitespace-normal break-words hover:underline" href={path}>
{path}
</a>
</li>
<li>
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
{locale.COMMON.COPYRIGHT_NOTICE}
</li>
</ul>
</section>
);
}
51 changes: 51 additions & 0 deletions themes/commerce/components/ArticleLock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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 dark:text-gray-300 text-black'>{locale.COMMON.ARTICLE_LOCK_TIPS}</div>
<div className='flex mx-4'>
<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 bg-gray-100 dark:bg-gray-500'>
</input>
<div onClick={submitPassword} className="px-3 whitespace-nowrap cursor-pointer items-center justify-center py-2 bg-red-500 hover:bg-red-400 text-white rounded-r duration-300" >
<i className={'duration-200 cursor-pointer fas fa-key'} >&nbsp;{locale.COMMON.SUBMIT}</i>
</div>
</div>
<div id='tips'>
</div>
</div>
</div>
}
60 changes: 60 additions & 0 deletions themes/commerce/components/ArticleRecommend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Link from 'next/link'
import CONFIG from '../config'
import { siteConfig } from '@/lib/config'
import { useGlobal } from '@/lib/global'
import LazyImage from '@/components/LazyImage'

/**
* 关联推荐文章
* @param {prev,next} param0
* @returns
*/
export default function ArticleRecommend({ recommendPosts, siteInfo }) {
const { locale } = useGlobal()

if (
!CONFIG.ARTICLE_RECOMMEND ||
!recommendPosts ||
recommendPosts.length === 0
) {
return <></>
}

return (
<div className="pt-8">
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
<div className='dark:text-gray-300'>
<i className="mr-2 fas fa-thumbs-up" />
{locale.COMMON.RELATE_POSTS}
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{recommendPosts.map(post => {
const headerImage = post?.pageCoverThumbnail
? post.pageCoverThumbnail
: siteInfo?.pageCover

return (
(<Link
key={post.id}
title={post.title}
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
passHref
className="flex h-40 cursor-pointer overflow-hidden">

<div className="h-full w-full relative group">
<div className="flex items-center justify-center w-full h-full duration-300 ">
<div className="z-10 text-lg px-4 font-bold text-white text-center shadow-text select-none">
{post.title}
</div>
</div>
<LazyImage src={headerImage} className='absolute top-0 w-full h-full object-cover object-center group-hover:scale-110 group-hover:brightness-50 transform duration-200' />
</div>

</Link>)
)
})}
</div>
</div>
)
}
49 changes: 49 additions & 0 deletions themes/commerce/components/BlogPostArchive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Link from 'next/link'
import { siteConfig } from '@/lib/config'

/**
* 博客归档列表
* @param posts 所有文章
* @param archiveTitle 归档标题
* @returns {JSX.Element}
* @constructor
*/
const BlogPostArchive = ({ posts = [], archiveTitle }) => {
if (!posts || posts.length === 0) {
return <></>
} else {
return (
<div>
<div
className="pt-16 pb-4 text-3xl dark:text-gray-300"
id={archiveTitle}
>
{archiveTitle}
</div>
<ul>
{posts?.map(post => (
<li
key={post.id}
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-red-500 dark:hover:border-red-300 dark:border-red-400 transform duration-500"
>
<div id={post?.publishDay}>
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
&nbsp;
<Link
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
passHref
className="dark:text-gray-400 dark:hover:text-red-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">

{post.title}

</Link>
</div>
</li>
))}
</ul>
</div>
)
}
}

export default BlogPostArchive

0 comments on commit 7fc3063

Please sign in to comment.