超级加倍优化✅
This commit is contained in:
parent
a019180b73
commit
5da1f4b21b
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
- [x] 简洁的响应式设计
|
- [x] 简洁的响应式设计
|
||||||
- [x] 流畅的动画和页面过渡
|
- [x] 流畅的动画和页面过渡
|
||||||
|
- [x] 丝滑的阻尼滚动效果(自定义开启/关闭)
|
||||||
- [x] 两列布局
|
- [x] 两列布局
|
||||||
- [x] 阅读时间
|
- [x] 阅读时间
|
||||||
- [x] 字数统计
|
- [x] 字数统计
|
||||||
@ -27,9 +28,12 @@
|
|||||||
- [x] 分类
|
- [x] 分类
|
||||||
- [x] 归档
|
- [x] 归档
|
||||||
- [x] 动态
|
- [x] 动态
|
||||||
|
- [x] 圈子
|
||||||
- [x] 关于
|
- [x] 关于
|
||||||
|
- [x] 留言板
|
||||||
- [x] 友情链接
|
- [x] 友情链接
|
||||||
- [x] 推荐文章
|
- [x] 推荐文章
|
||||||
|
- [x] 置顶文章
|
||||||
- [x] 谷歌广告
|
- [x] 谷歌广告
|
||||||
- [x] 内置 404 页面
|
- [x] 内置 404 页面
|
||||||
- [x] Sitemap 支持
|
- [x] Sitemap 支持
|
||||||
@ -114,6 +118,7 @@ date: 文章创建日期
|
|||||||
updated: 文章更新日期
|
updated: 文章更新日期
|
||||||
cover: "封面图URL (为空默认随机内置封面 /public/assets/images/banner)"
|
cover: "封面图URL (为空默认随机内置封面 /public/assets/images/banner)"
|
||||||
recommend: false # 是否推荐文章
|
recommend: false # 是否推荐文章
|
||||||
|
top: false # 是否置顶文章
|
||||||
hide: false # 是否隐藏文章
|
hide: false # 是否隐藏文章
|
||||||
---
|
---
|
||||||
```
|
```
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import swup from '@swup/astro';
|
|||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: 'https://www.vvhan.com',
|
site: 'https://www.vvhan.com',
|
||||||
|
build: { assets: 'vh_static' },
|
||||||
integrations: [
|
integrations: [
|
||||||
swup({
|
swup({
|
||||||
theme: false,
|
theme: false,
|
||||||
|
|||||||
@ -15,8 +15,7 @@
|
|||||||
"@astrojs/sitemap": "^3.2.1",
|
"@astrojs/sitemap": "^3.2.1",
|
||||||
"@swup/astro": "^1.5.0",
|
"@swup/astro": "^1.5.0",
|
||||||
"aplayer": "^1.10.1",
|
"aplayer": "^1.10.1",
|
||||||
"astro": "^5.4.1",
|
"astro": "^5.4.2",
|
||||||
"lenis": "^1.2.1",
|
|
||||||
"overlayscrollbars": "^2.11.1",
|
"overlayscrollbars": "^2.11.1",
|
||||||
"vanilla-lazyload": "^19.1.3",
|
"vanilla-lazyload": "^19.1.3",
|
||||||
"vh-plugin": "^1.2.2"
|
"vh-plugin": "^1.2.2"
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import "../styles/components/ArticleCard.less";
|
|||||||
---
|
---
|
||||||
|
|
||||||
<article class="vh-article-item vh-animation vh-animation-init">
|
<article class="vh-article-item vh-animation vh-animation-init">
|
||||||
<a class="vh-article-link" href={`/article/${post.data.id}`}>
|
<a class={`vh-article-link${post.data.top ? " active" : ""}`} href={`/article/${post.data.id}`}>
|
||||||
<section class="vh-article-banner"><Image src="/assets/images/lazy-loading.webp" data-vh-lz-src={ARTICLE_COVER} alt={post.data.title} width="10" height="10" /></section>
|
<section class="vh-article-banner"><Image src="/assets/images/lazy-loading.webp" data-vh-lz-src={ARTICLE_COVER} alt={post.data.title} width="10" height="10" /></section>
|
||||||
<section class="vh-article-desc">
|
<section class="vh-article-desc">
|
||||||
<header>
|
<header>
|
||||||
|
|||||||
@ -14,7 +14,8 @@ const blog = defineCollection({
|
|||||||
id: z.union([z.string(), z.number()]),
|
id: z.union([z.string(), z.number()]),
|
||||||
cover: z.string().optional(),
|
cover: z.string().optional(),
|
||||||
recommend: z.boolean().optional(),
|
recommend: z.boolean().optional(),
|
||||||
hide: z.boolean().optional()
|
hide: z.boolean().optional(),
|
||||||
|
top: z.boolean().optional()
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,14 @@
|
|||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import type { GetStaticPathsOptions } from "astro";
|
import type { GetStaticPathsOptions } from "astro";
|
||||||
import setSearchJson from "../utils/vhSearch";
|
import setSearchJson from "../utils/vhSearch";
|
||||||
|
import moveTopToFirst from "../utils/moveTopToFirst";
|
||||||
export async function getStaticPaths(options: GetStaticPathsOptions) {
|
export async function getStaticPaths(options: GetStaticPathsOptions) {
|
||||||
const { paginate } = options;
|
const { paginate } = options;
|
||||||
const posts = (await getCollection("blog")).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
|
const posts = (await getCollection("blog")).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
|
||||||
// 生成 Search JSON 文件 ======
|
// 置顶文章功能
|
||||||
|
moveTopToFirst(posts);
|
||||||
|
// 生成 Search JSON 文件
|
||||||
await setSearchJson(posts);
|
await setSearchJson(posts);
|
||||||
// 生成 Search JSON 文件 ======
|
|
||||||
// 隐藏的文章不显示
|
// 隐藏的文章不显示
|
||||||
return paginate(
|
return paginate(
|
||||||
posts.filter(i => !i.data.hide),
|
posts.filter(i => !i.data.hide),
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const scrollChangeFn = () => {
|
|||||||
const backTopFn = () => {
|
const backTopFn = () => {
|
||||||
(window as any).vhlenis && (window as any).vhlenis.stop();
|
(window as any).vhlenis && (window as any).vhlenis.stop();
|
||||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
(window as any).vhlenis.start();
|
(window as any).vhlenis && (window as any).vhlenis.start();
|
||||||
};
|
};
|
||||||
// 页面更新,初始化函数======
|
// 页面更新,初始化函数======
|
||||||
// 回顶部DOM
|
// 回顶部DOM
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const FriendsInit = async (data: any) => {
|
|||||||
if (typeof data === 'string') {
|
if (typeof data === 'string') {
|
||||||
res = await $GET(api);
|
res = await $GET(api);
|
||||||
}
|
}
|
||||||
friendsDOM.innerHTML = res.map((i: any) => `<article><a href="${i.link}" target="_blank" rel="noopener nofollow"><header><h2>${i.title}</h2></header><p>${i.content}</p><footer><span><img src="https://icon.bqb.cool/?url=${i.link.split('//')[1].split('/')[0]}" />${i.auther}</span><time>${fmtDate(i.date)}前</time></footer></a></article>`).join('');
|
friendsDOM.innerHTML = res.map((i: any) => `<article><a href="${i.link}" target="_blank" rel="noopener nofollow"><header><h2>${i.title}</h2></header><p>${i.content}</p><footer><span><img src="https://icon.bqb.cool/?url=${i.link.split('//')[1].split('/')[0]}" /><em>${i.auther}</em></span><time>${fmtDate(i.date, false)}前</time></footer></a></article>`).join('');
|
||||||
} catch {
|
} catch {
|
||||||
vh.Toast('获取数据失败')
|
vh.Toast('获取数据失败')
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/scripts/HanAnalytics.ts
Normal file
9
src/scripts/HanAnalytics.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
// Han Analytics 统计
|
||||||
|
import SITE_INFO from "../config";
|
||||||
|
import { LoadScript } from "../utils/index";
|
||||||
|
|
||||||
|
export default async () => {
|
||||||
|
const { HanAnalytics } = SITE_INFO;
|
||||||
|
HanAnalytics.enable && LoadScript(`${HanAnalytics.server}/tracker.min.js`, [{ k: "data-website-id", v: HanAnalytics.siteId }]);
|
||||||
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
import { inRouter, outRouter } from "../utils/updateRouter";
|
import { inRouter, outRouter } from "../utils/updateRouter";
|
||||||
// 鼠标滚动阻尼效果
|
|
||||||
import LenisInit from './Lenis';
|
|
||||||
// 初始化文章代码块
|
// 初始化文章代码块
|
||||||
import codeInit from "../scripts/Code";
|
import codeInit from "../scripts/Code";
|
||||||
// 初始化视频播放器
|
// 初始化视频播放器
|
||||||
@ -30,9 +28,9 @@ import initMobileSidebar from "../scripts/MobileSidebar";
|
|||||||
// Google 广告
|
// Google 广告
|
||||||
import GoogleAdInit from "../scripts/GoogleAd";
|
import GoogleAdInit from "../scripts/GoogleAd";
|
||||||
// Han Analytics 统计
|
// Han Analytics 统计
|
||||||
import SITE_INFO from "../config";
|
import HanAnalyticsInit from "../scripts/HanAnalytics";
|
||||||
const { HanAnalytics } = SITE_INFO;
|
// SmoothScroll 滚动优化
|
||||||
import { LoadScript } from "../utils/index";
|
import SmoothScroll from "../scripts/Smoothscroll";
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
@ -40,8 +38,6 @@ import { LoadScript } from "../utils/index";
|
|||||||
const videoList: any[] = [];
|
const videoList: any[] = [];
|
||||||
const MusicList: any[] = [];
|
const MusicList: any[] = [];
|
||||||
const indexInit = async (only: boolean = true) => {
|
const indexInit = async (only: boolean = true) => {
|
||||||
// 鼠标滚动阻尼效果
|
|
||||||
only && LenisInit();
|
|
||||||
// 预加载搜索数据
|
// 预加载搜索数据
|
||||||
only && searchFn("");
|
only && searchFn("");
|
||||||
// 初始化搜索功能
|
// 初始化搜索功能
|
||||||
@ -52,6 +48,8 @@ const indexInit = async (only: boolean = true) => {
|
|||||||
only && BackTopInitFn();
|
only && BackTopInitFn();
|
||||||
// 移动端侧边栏初始化
|
// 移动端侧边栏初始化
|
||||||
only && initMobileSidebar();
|
only && initMobileSidebar();
|
||||||
|
// SmoothScroll 滚动优化
|
||||||
|
only && SmoothScroll();
|
||||||
// 顶部导航 Current 状态
|
// 顶部导航 Current 状态
|
||||||
initLinkCurrent()
|
initLinkCurrent()
|
||||||
// 初始化文章代码块
|
// 初始化文章代码块
|
||||||
@ -68,12 +66,12 @@ const indexInit = async (only: boolean = true) => {
|
|||||||
initTalking();
|
initTalking();
|
||||||
// Google 广告
|
// Google 广告
|
||||||
GoogleAdInit();
|
GoogleAdInit();
|
||||||
|
// Han Analytics 统计
|
||||||
|
HanAnalyticsInit();
|
||||||
// 文章视频播放器初始化
|
// 文章视频播放器初始化
|
||||||
videoInit(videoList);
|
videoInit(videoList);
|
||||||
// 文章音乐播放器初始化
|
// 文章音乐播放器初始化
|
||||||
musicInit(MusicList);
|
musicInit(MusicList);
|
||||||
// Han Analytics 统计
|
|
||||||
HanAnalytics.enable && LoadScript(`${HanAnalytics.server}/tracker.min.js`, [{ k: "data-website-id", v: HanAnalytics.siteId }]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
import Lenis from "lenis";
|
|
||||||
|
|
||||||
const IncludeClassName = ['vh-code-box', 'vh-search-list'];
|
|
||||||
(window as any).vhlenis = new Lenis({
|
|
||||||
prevent: (node) => IncludeClassName.some((i: string) => node.className.includes(i))
|
|
||||||
});
|
|
||||||
const lenisInit = (time: any) => {
|
|
||||||
(window as any).vhlenis.raf(time)
|
|
||||||
requestAnimationFrame(lenisInit)
|
|
||||||
}
|
|
||||||
(window as any).vhlenis.on('scroll', () => {
|
|
||||||
if (window.scrollY + window.innerHeight >= document.documentElement.scrollHeight) {
|
|
||||||
(window as any).vhlenis.stop();
|
|
||||||
(window as any).vhlenis.start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default () => requestAnimationFrame(lenisInit)
|
|
||||||
@ -4,7 +4,6 @@ import { $GET } from '../utils/index'
|
|||||||
import 'aplayer/dist/APlayer.min.css';
|
import 'aplayer/dist/APlayer.min.css';
|
||||||
import APlayer from 'aplayer';
|
import APlayer from 'aplayer';
|
||||||
|
|
||||||
declare const APlayer: any;
|
|
||||||
// 初始化音乐播放器
|
// 初始化音乐播放器
|
||||||
export default async (MusicList: any[]) => {
|
export default async (MusicList: any[]) => {
|
||||||
const musicDOM: any = document.querySelectorAll(".vh-node.vh-vhMusic");
|
const musicDOM: any = document.querySelectorAll(".vh-node.vh-vhMusic");
|
||||||
|
|||||||
7
src/scripts/Smoothscroll.ts
Normal file
7
src/scripts/Smoothscroll.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// SmoothScroll 滚动优化
|
||||||
|
import { LoadScript } from "../utils/index";
|
||||||
|
declare const SmoothScroll: any;
|
||||||
|
export default async () => {
|
||||||
|
await LoadScript("/assets/js/smoothscroll.min.js");
|
||||||
|
SmoothScroll({ stepSize: 118, animationTime: 666 })
|
||||||
|
};
|
||||||
@ -3,7 +3,6 @@ section.vh-container {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
|
|
||||||
&>header {
|
&>header {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 2rem 1rem 1rem;
|
padding: 2rem 1rem 1rem;
|
||||||
@ -70,6 +69,14 @@ section.vh-container {
|
|||||||
box-shadow: 0 12px 8px 6px rgba(7, 17, 27, 0.05);
|
box-shadow: 0 12px 8px 6px rgba(7, 17, 27, 0.05);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
.aplayer-list {
|
||||||
|
max-height: max-content !important;
|
||||||
|
|
||||||
|
&>ol {
|
||||||
|
max-height: 566px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&>.tag-list {
|
&>.tag-list {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
|
|||||||
@ -62,6 +62,8 @@ img {
|
|||||||
// 隐藏滚动条
|
// 隐藏滚动条
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
|
// 平滑滚动
|
||||||
|
scroll-behavior: smooth;
|
||||||
// 消除边框
|
// 消除边框
|
||||||
outline: none; // 隐藏滚动条
|
outline: none; // 隐藏滚动条
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: max-content;
|
height: max-content;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&>span,
|
&>span,
|
||||||
&>time {
|
&>time {
|
||||||
@ -64,18 +65,33 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
width: max-content;
|
|
||||||
height: 1.56rem;
|
height: 1.56rem;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&>em {
|
||||||
|
font-style: normal;
|
||||||
|
flex: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
&>img {
|
&>img {
|
||||||
|
flex-shrink: 0;
|
||||||
width: 1.56rem;
|
width: 1.56rem;
|
||||||
height: 1.56rem;
|
height: 1.56rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&>span {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&>time {
|
&>time {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: max-content;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background: #F7F7F7;
|
background: #F7F7F7;
|
||||||
border-radius: 0.8rem;
|
border-radius: 0.8rem;
|
||||||
|
|||||||
@ -20,6 +20,7 @@ section.article-list {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&>a.vh-article-link {
|
&>a.vh-article-link {
|
||||||
|
position: relative;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -38,7 +39,48 @@ section.article-list {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
&::before {
|
||||||
|
content: "置顶";
|
||||||
|
position: absolute;
|
||||||
|
top: 1.6rem;
|
||||||
|
left: 0.66rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0.18rem 1rem;
|
||||||
|
width: max-content;
|
||||||
|
height: max-content;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 0.66rem;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
/* 确保元素有半透明背景 */
|
||||||
|
background: #00000033;
|
||||||
|
box-shadow: 0 2rem 1rem rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 1;
|
||||||
|
/* 高斯模糊效果 */
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
-webkit-backdrop-filter: blur(6px);
|
||||||
|
/* 兼容旧版浏览器 */
|
||||||
|
}
|
||||||
|
|
||||||
|
&>.vh-article-banner {
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.06);
|
||||||
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
&>.vh-article-banner {
|
&>.vh-article-banner {
|
||||||
|
position: relative;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -71,6 +71,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tk-admin {
|
||||||
|
|
||||||
|
.tk-login {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tk-admin-warn p {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 评论输入框Focus边框颜色
|
// 评论输入框Focus边框颜色
|
||||||
.el-input__inner:focus,
|
.el-input__inner:focus,
|
||||||
.el-textarea__inner:focus {
|
.el-textarea__inner:focus {
|
||||||
|
|||||||
1
src/type/aplayer.d.ts
vendored
Normal file
1
src/type/aplayer.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module 'aplayer';
|
||||||
@ -59,10 +59,8 @@ async function* createImageIterator(dir: string) {
|
|||||||
|
|
||||||
const targetDir = path.resolve(__dirname, '../../public/assets/images/banner/'); // 目标目录
|
const targetDir = path.resolve(__dirname, '../../public/assets/images/banner/'); // 目标目录
|
||||||
const fileIter = createImageIterator(targetDir);
|
const fileIter = createImageIterator(targetDir);
|
||||||
const getCover = async (filename: string | null | undefined) => {
|
export default async (filename: string | null | undefined) => {
|
||||||
if (filename) return filename;
|
if (filename) return filename;
|
||||||
const { value } = await fileIter.next();
|
const { value } = await fileIter.next();
|
||||||
return SITE_INFO.Site + `/assets/images/banner/${value}`
|
return SITE_INFO.Site + `/assets/images/banner/${value}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getCover;
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
const COMMITER_DATE_ISO_FORMAT = "%cI";
|
|
||||||
|
|
||||||
export default function getFileCreateTime(filePath: string, type: string): Date {
|
|
||||||
try {
|
|
||||||
const result = execSync(`git log --pretty=format:"${COMMITER_DATE_ISO_FORMAT}" ${filePath}`).toString();
|
|
||||||
if (!result) {
|
|
||||||
throw new Error('Git command failed to execute');
|
|
||||||
}
|
|
||||||
const commits = result.split(/\r?\n/g);
|
|
||||||
return new Date(commits[type == 'create' ? commits.length - 1 : 0]);
|
|
||||||
} catch (e) {
|
|
||||||
// not committed yet
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -24,8 +24,8 @@ const getTags = () => {
|
|||||||
|
|
||||||
// 获取推荐文章 (给文章添加 recommend: true 字段)
|
// 获取推荐文章 (给文章添加 recommend: true 字段)
|
||||||
const getRecommendArticles = () => {
|
const getRecommendArticles = () => {
|
||||||
const recommendList = posts.filter(i => i.data.recommend).slice(0, 6);
|
const recommendList = posts.filter(i => i.data.recommend);
|
||||||
return (recommendList.length ? recommendList : posts).slice(0, 6).map(async i => ({ title: i.data.title, date: i.data.date, id: i.data.id, cover: await getCover(i.data.cover) }))
|
return (recommendList.length ? recommendList : posts.slice(0, 6)).map(async i => ({ title: i.data.title, date: i.data.date, id: i.data.id, cover: await getCover(i.data.cover) }))
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getCategories, getTags, getRecommendArticles };
|
export { getCategories, getTags, getRecommendArticles };
|
||||||
@ -11,7 +11,7 @@ const getDescription = (post: any, num: number = 150) => (post.rendered ? post.r
|
|||||||
//处理时间
|
//处理时间
|
||||||
const fmtTime = (time: any, fmt: string = 'MMMM D, YYYY') => dayjs(time).utc().format(fmt)
|
const fmtTime = (time: any, fmt: string = 'MMMM D, YYYY') => dayjs(time).utc().format(fmt)
|
||||||
// 处理日期
|
// 处理日期
|
||||||
const fmtDate = (time: string | Date) => {
|
const fmtDate = (time: string | Date, hours_status = true) => {
|
||||||
const now = dayjs();
|
const now = dayjs();
|
||||||
const past = dayjs(time);
|
const past = dayjs(time);
|
||||||
// 计算各时间单位,逐步扣除已计算的部分
|
// 计算各时间单位,逐步扣除已计算的部分
|
||||||
@ -31,9 +31,9 @@ const fmtDate = (time: string | Date) => {
|
|||||||
years && `${years}年`,
|
years && `${years}年`,
|
||||||
months && `${months}月`,
|
months && `${months}月`,
|
||||||
days && `${days}天`,
|
days && `${days}天`,
|
||||||
hours && !years && !months && `${hours}小时`,
|
hours_status ? hours && !years && !months && `${hours}小时` : 0,
|
||||||
minutes && !years && !months && !days && `${minutes}分`,
|
hours_status ? minutes && !years && !months && !days && `${minutes}分` : '',
|
||||||
seconds && !years && !months && !days && !hours && `${seconds}秒`
|
hours_status ? seconds && !years && !months && !days && !hours && `${seconds}秒` : ''
|
||||||
].filter(Boolean).join('');
|
].filter(Boolean).join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
8
src/utils/moveTopToFirst.ts
Normal file
8
src/utils/moveTopToFirst.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default (arr: Array<any>) => {
|
||||||
|
const index = arr.findIndex((item: any) => item.data.top === true);
|
||||||
|
if (index !== -1) {
|
||||||
|
const [item] = arr.splice(index, 1);
|
||||||
|
arr.unshift(item);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ import fs from 'fs/promises';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as cheerio from 'cheerio';
|
import * as cheerio from 'cheerio';
|
||||||
|
|
||||||
const setSearchJson = async (posts: any[]) => {
|
export default async (posts: any[]) => {
|
||||||
const searchIndex = posts.map(i => {
|
const searchIndex = posts.map(i => {
|
||||||
const $ = cheerio.load(`<body>${i.rendered.html}</body>`);
|
const $ = cheerio.load(`<body>${i.rendered.html}</body>`);
|
||||||
return {
|
return {
|
||||||
@ -25,6 +25,4 @@ const setSearchJson = async (posts: any[]) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error writing search index file:', error);
|
console.error('Error writing search index file:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default setSearchJson;
|
|
||||||
Loading…
x
Reference in New Issue
Block a user