Skip to content

Commit

Permalink
plog 点击图片跳转
Browse files Browse the repository at this point in the history
  • Loading branch information
tangly1024 committed Mar 14, 2024
1 parent 097eee1 commit 7826cef
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 104 deletions.
80 changes: 41 additions & 39 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ export const isSearchEngineBot = () => {
return false
}
// 获取用户代理字符串
const userAgent = navigator.userAgent;
const userAgent = navigator.userAgent
// 使用正则表达式检测是否包含搜索引擎爬虫关键字
return /Googlebot|bingbot|Baidu/.test(userAgent)
}

/**
* 组件持久化
*/
export const memorize = (Component) => {
const MemoizedComponent = (props) => {
export const memorize = Component => {
const MemoizedComponent = props => {
return <Component {...props} />
}
return memo(MemoizedComponent)
Expand All @@ -34,26 +34,26 @@ export const memorize = (Component) => {
// 转换外链
export function sliceUrlFromHttp(str) {
// 检查字符串是否包含http
if (str.includes('http:') || str.includes('https:')) {
if (str?.includes('http:') || str?.includes('https:')) {
// 如果包含,找到http的位置
const index = str.indexOf('http');
const index = str?.indexOf('http')
// 返回http之后的部分
return str.slice(index, str.length);
return str.slice(index, str.length)
} else {
// 如果不包含,返回原字符串
return str;
return str
}
}

// 检查是否外链
export function checkContainHttp(str) {
// 检查字符串是否包含http
if (str.includes('http:') || str.includes('https:')) {
if (str?.includes('http:') || str?.includes('https:')) {
// 如果包含,找到http的位置
return str.indexOf('http') > -1
return str?.indexOf('http') > -1
} else {
// 不包含
return false;
return false
}
}

Expand All @@ -65,7 +65,10 @@ export function checkContainHttp(str) {
*/
export function loadExternalResource(url, type) {
// 检查是否已存在
const elements = type === 'js' ? document.querySelectorAll(`[src='${url}']`) : document.querySelectorAll(`[href='${url}']`)
const elements =
type === 'js'
? document.querySelectorAll(`[src='${url}']`)
: document.querySelectorAll(`[href='${url}']`)

return new Promise((resolve, reject) => {
if (elements.length > 0 || !url) {
Expand Down Expand Up @@ -112,9 +115,11 @@ export function getQueryVariable(key) {
const vars = query.split('&')
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === key) { return pair[1] }
if (pair[0] === key) {
return pair[1]
}
}
return (false)
return false
}
/**
* 获取 URL 中指定参数的值
Expand All @@ -124,9 +129,9 @@ export function getQueryVariable(key) {
*/
export function getQueryParam(url, param) {
// 移除哈希部分
const urlWithoutHash = url.split('#')[0];
const searchParams = new URLSearchParams(urlWithoutHash.split('?')[1]);
return searchParams.get(param);
const urlWithoutHash = url.split('#')[0]
const searchParams = new URLSearchParams(urlWithoutHash.split('?')[1])
return searchParams.get(param)
}

/**
Expand Down Expand Up @@ -157,7 +162,7 @@ export function mergeDeep(target, ...sources) {
* @returns {boolean}
*/
export function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item))
return item && typeof item === 'object' && !Array.isArray(item)
}

/**
Expand Down Expand Up @@ -210,10 +215,7 @@ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
* @returns {*}
*/
export const getListByPage = function (list, pageIndex, pageSize) {
return list.slice(
0,
pageIndex * pageSize
)
return list.slice(0, pageIndex * pageSize)
}

/**
Expand All @@ -230,7 +232,7 @@ export const isMobile = () => {
// isMobile = true
// }

if (!isMobile && (/Mobi|Android|iPhone/i.test(navigator.userAgent))) {
if (!isMobile && /Mobi|Android|iPhone/i.test(navigator.userAgent)) {
isMobile = true
}

Expand All @@ -249,41 +251,41 @@ export const isMobile = () => {
* 扫描页面上的所有文本节点,将url格式的文本转为可点击链接
* @param {*} node
*/
export const scanAndConvertToLinks = (node) => {
export const scanAndConvertToLinks = node => {
if (node.nodeType === Node.TEXT_NODE) {
const text = node.textContent;
const urlRegex = /https?:\/\/[^\s]+/g;
let lastIndex = 0;
let match;
const text = node.textContent
const urlRegex = /https?:\/\/[^\s]+/g
let lastIndex = 0
let match

const newNode = document.createElement('span');
const newNode = document.createElement('span')

while ((match = urlRegex.exec(text)) !== null) {
const beforeText = text.substring(lastIndex, match.index);
const url = match[0];
const beforeText = text.substring(lastIndex, match.index)
const url = match[0]

if (beforeText) {
newNode.appendChild(document.createTextNode(beforeText));
newNode.appendChild(document.createTextNode(beforeText))
}

const link = document.createElement('a');
link.href = url;
const link = document.createElement('a')
link.href = url
link.target = '_blank'
link.textContent = url;
link.textContent = url

newNode.appendChild(link);
newNode.appendChild(link)

lastIndex = urlRegex.lastIndex;
lastIndex = urlRegex.lastIndex
}

if (lastIndex < text.length) {
newNode.appendChild(document.createTextNode(text.substring(lastIndex)));
newNode.appendChild(document.createTextNode(text.substring(lastIndex)))
}

node.parentNode.replaceChild(newNode, node);
node.parentNode.replaceChild(newNode, node)
} else if (node.nodeType === Node.ELEMENT_NODE) {
for (const childNode of node.childNodes) {
scanAndConvertToLinks(childNode);
scanAndConvertToLinks(childNode)
}
}
}
179 changes: 114 additions & 65 deletions themes/plog/components/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,28 @@ import Link from 'next/link'
import { siteConfig } from '@/lib/config'
import LazyImage from '@/components/LazyImage'
import { compressImage } from '@/lib/notion/mapImage'
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'

/**
* 弹出框
*/
export default function Modal(props) {
const { showModal, setShowModal, modalContent, setModalContent } = usePlogGlobal()
const { showModal, setShowModal, modalContent, setModalContent } =
usePlogGlobal()
const { siteInfo, posts } = props
const cancelButtonRef = useRef(null)
const img = compressImage(modalContent?.pageCover || siteInfo?.pageCover, 1200, 85, 'webp')
const img = compressImage(
modalContent?.pageCover || siteInfo?.pageCover,
1200,
85,
'webp'
)
const imgRef = useRef(null)

const url = checkContainHttp(modalContent?.slug)
? sliceUrlFromHttp(modalContent?.slug)
: `${siteConfig('SUB_PATH', '')}/${modalContent?.slug}`

// 添加loading状态
const [loading, setLoading] = useState(true)

Expand Down Expand Up @@ -53,73 +64,111 @@ export default function Modal(props) {
}

return (
<Transition.Root show={showModal} as={Fragment}>
<Dialog as="div" className="relative z-20" initialFocus={cancelButtonRef} onClose={handleClose}>
{/* 遮罩 */}
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }} className="fixed inset-0 glassmorphism transition-opacity" />
</Transition.Child>
<Transition.Root show={showModal} as={Fragment}>
<Dialog
as="div"
className="relative z-20"
initialFocus={cancelButtonRef}
onClose={handleClose}
>
{/* 遮罩 */}
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}
className="fixed inset-0 glassmorphism transition-opacity"
/>
</Transition.Child>

<div className="fixed inset-0 z-30 overflow-y-auto">
<div className="flex min-h-full justify-center p-4 text-center items-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 scale-50 w-0"
enterTo={'opacity-100 translate-y-0 max-w-screen'}
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 scale-100 max-w-screen"
leaveTo="opacity-0 translate-y-4 scale-50 w-0"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-xl text-left shadow-xl transition-all ">
{/* 添加loading状态 */}
<div className={`bg-hexo-black-gray w-32 h-32 flex justify-center items-center ${loading ? '' : 'hidden'}`}>
<ArrowPath className='w-10 h-10 animate-spin text-gray-200' />
</div>

{/* 添加onLoad事件处理函数 */}
<LazyImage onLoad={handleImageLoad} src={img} ref={imgRef} style={{ display: loading ? 'none' : 'block' }} className={`w-full max-w-7xl max-h-[90vh] shadow-xl ${!loading ? ' animate__animated animate__fadeIn' : ''}`} />
<div className="fixed inset-0 z-30 overflow-y-auto">
<div className="flex min-h-full justify-center p-4 text-center items-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 scale-50 w-0"
enterTo={'opacity-100 translate-y-0 max-w-screen'}
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 scale-100 max-w-screen"
leaveTo="opacity-0 translate-y-4 scale-50 w-0"
>
<Dialog.Panel className="group relative transform overflow-hidden rounded-xl text-left shadow-xl transition-all ">
{/* 添加onLoad事件处理函数 */}
{/* 添加loading状态 */}
<div
className={`bg-hexo-black-gray w-32 h-32 flex justify-center items-center ${loading ? '' : 'hidden'}`}
>
<ArrowPath className="w-10 h-10 animate-spin text-gray-200" />
</div>

{!loading && (<>
<div className='absolute bottom-0 left-0 m-4 z-20'>
<Link href={`${siteConfig('SUB_PATH', '')}/${modalContent.slug}`}>
<div className='flex'>
<h2 style={{ textShadow: '0.1em 0.1em 0.2em black' }} className='text-2xl md:text-5xl text-white mb-4 px-2 py-1 rounded-lg'>{modalContent?.title}</h2>
</div>
</Link>
<Link href={`${siteConfig('SUB_PATH', '')}/${modalContent.slug}`}>
<div style={{ textShadow: '0.1em 0.1em 0.2em black' }} className={'line-clamp-3 md:line-clamp-none overflow-hidden cursor-pointer text-gray-50 rounded-lg m-2'}>
{modalContent?.summary}
</div>
</Link>
<Link href={url}>
<LazyImage
onLoad={handleImageLoad}
src={img}
ref={imgRef}
style={{ display: loading ? 'none' : 'block' }}
className={`w-full select-none max-w-7xl max-h-[90vh] shadow-xl ${!loading ? ' animate__animated animate__fadeIn' : ''}`}
/>
</Link>

{modalContent?.category && (
<div className='flex'>
<Link href={`/category/${modalContent?.category}`} className='text-xs rounded-lg mt-3 px-2 py-1 bg-black bg-opacity-20 text-white hover:bg-blue-700 hover:text-white duration-200'>
{modalContent?.category}
</Link>
</div>
)}
</div>
<div className='z-10 absolute hover:opacity-50 opacity-0 duration-200 transition-opacity w-full top-0 left-0 px-4 h-full items-center flex justify-between'>
<div onClick={prev}><ChevronLeft className='cursor-pointer w-24 h-32 hover:opacity-100 stroke-white stroke-1 scale-y-150' /></div>
<div onClick={next}><ChevronRight className='cursor-pointer w-24 h-32 hover:opacity-100 stroke-white stroke-1 scale-y-150' /></div>
</div>
</>)}
{!loading && (
<>
<div className="absolute bottom-0 left-0 m-4 z-20">
<div className="flex">
<h2
style={{ textShadow: '0.1em 0.1em 0.2em black' }}
className="text-2xl md:text-5xl text-white mb-4 px-2 py-1 rounded-lg"
>
{modalContent?.title}
</h2>
</div>
<div
style={{ textShadow: '0.1em 0.1em 0.2em black' }}
className={
'line-clamp-3 md:line-clamp-none overflow-hidden cursor-pointer text-gray-50 rounded-lg m-2'
}
>
{modalContent?.summary}
</div>

</Dialog.Panel>
</Transition.Child>
{modalContent?.category && (
<div className="flex">
<Link
href={`/category/${modalContent?.category}`}
className="text-xs rounded-lg mt-3 px-2 py-1 bg-black bg-opacity-20 text-white hover:bg-blue-700 hover:text-white duration-200"
>
{modalContent?.category}
</Link>
</div>
)}
</div>
</div>
</Dialog>
</Transition.Root>
{/* <div className="z-10 absolute hover:opacity-50 opacity-0 duration-200 transition-opacity w-full top-0 left-0 px-4 h-full items-center flex justify-between"> */}
<div
onClick={prev}
className="z-10 absolute left-0 top-1/2 -mt-12 group-hover:opacity-50 opacity-0 duration-200 transition-opacity"
>
<ChevronLeft className="cursor-pointer w-24 h-32 hover:opacity-100 stroke-white stroke-1 scale-y-150" />
</div>
<div
onClick={next}
className="z-10 absolute right-0 top-1/2 -mt-12 group-hover:opacity-50 opacity-0 duration-200 transition-opacity"
>
<ChevronRight className="cursor-pointer w-24 h-32 hover:opacity-100 stroke-white stroke-1 scale-y-150" />
</div>
{/* </div> */}
</>
)}
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
)
}

0 comments on commit 7826cef

Please sign in to comment.