优化样式及部分逻辑

This commit is contained in:
Han 2025-05-13 10:17:49 +08:00
parent 14d4e6e94b
commit 2aa978451d
14 changed files with 223 additions and 181 deletions

View File

@ -12,13 +12,13 @@
"ondev": "astro preferences enable devToolbar" "ondev": "astro preferences enable devToolbar"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^4.2.3", "@astrojs/mdx": "^4.2.6",
"@astrojs/rss": "^4.0.11", "@astrojs/rss": "^4.0.11",
"@astrojs/sitemap": "^3.3.0", "@astrojs/sitemap": "^3.4.0",
"@swup/astro": "^1.6.0", "@swup/astro": "^1.6.0",
"aplayer": "^1.10.1", "aplayer": "^1.10.1",
"astro": "^5.6.0", "astro": "^5.7.12",
"overlayscrollbars": "^2.11.1", "overlayscrollbars": "^2.11.2",
"vanilla-lazyload": "^19.1.3", "vanilla-lazyload": "^19.1.3",
"vh-plugin": "^1.2.2" "vh-plugin": "^1.2.2"
}, },
@ -26,10 +26,10 @@
"@playform/compress": "^0.1.9", "@playform/compress": "^0.1.9",
"@types/dplayer": "^1.25.5", "@types/dplayer": "^1.25.5",
"@types/nprogress": "^0.2.3", "@types/nprogress": "^0.2.3",
"@waline/client": "^3.5.6", "@waline/client": "^3.5.7",
"cheerio": "^1.0.0", "cheerio": "^1.0.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"less": "^4.2.2", "less": "^4.3.0",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"rehype-katex": "^7.0.1", "rehype-katex": "^7.0.1",
@ -37,7 +37,7 @@
"remark-directive": "^4.0.0", "remark-directive": "^4.0.0",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"remark-sectionize": "^2.1.0", "remark-sectionize": "^2.1.0",
"typescript": "^5.8.2", "typescript": "^5.8.3",
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.0.0"
}, },
"pnpm": { "pnpm": {

View File

@ -10,16 +10,14 @@ const ARTICLE_COVER: string = await getCover(post.data.cover);
import "./ArticleCard.less"; import "./ArticleCard.less";
--- ---
<article class="vh-article-item vh-animation vh-animation-init"> <article class={`vh-article-item vh-animation vh-animation-init vh-article-link${post.data.top ? " active" : ""}`}>
<a class={`vh-article-link${post.data.top ? " active" : ""}`} href={`/article/${post.data.id}`}>
<section class="vh-article-banner"><img src="/assets/images/lazy-loading.webp" data-vh-lz-src={ARTICLE_COVER} alt={post.data.title} /></section> <section class="vh-article-banner"><img src="/assets/images/lazy-loading.webp" data-vh-lz-src={ARTICLE_COVER} alt={post.data.title} /></section>
<section class="vh-article-desc">
<header> <header>
<span class={`vh-article-cat vh-cat-${post.data.categories}`}>{post.data.categories}</span> <h3><a class={`vh-article-cat vh-cat-${post.data.categories}`} href={`/categories/${post.data.categories}`}>{post.data.categories}</a><time>{fmtTime(post.data.date)}</time></h3>
<h2 class="title vh-ellipsis">{post.data.title}</h2> <h1 class="title"><a class="vh-ellipsis" href={`/article/${post.data.id}`}>{post.data.title}</a></h1>
</header> </header>
<p class="vh-article-excerpt vh-ellipsis line-2">{description}</p> <h2 class="vh-article-excerpt vh-ellipsis line-2">{description}</h2>
<footer>{fmtTime(post.data.date)}</footer> <h4 class="vh-article-taglist vh-ellipsis">
</section> {post.data.tags.map((tag: string) => <a href={`/tag/${tag}`}>{tag}</a>)}
</a> </h4>
</article> </article>

View File

@ -16,7 +16,10 @@
overflow: hidden; overflow: hidden;
&>.vh-article-item { &>.vh-article-item {
position: relative;
box-sizing: border-box; box-sizing: border-box;
display: flex;
flex-direction: column;
width: 100%; width: 100%;
height: initial; height: initial;
min-height: max-content; min-height: max-content;
@ -25,18 +28,6 @@
background-color: #fff; background-color: #fff;
overflow: hidden; overflow: hidden;
&>a.vh-article-link {
position: relative;
box-sizing: border-box;
display: flex;
flex-direction: column;
width: 100%;
height: max-content;
min-height: 100%;
border-radius: 0.618rem;
overflow: hidden;
transition: background 0.18s;
&:hover { &:hover {
&>.vh-article-banner { &>.vh-article-banner {
&>img { &>img {
@ -100,24 +91,24 @@
} }
} }
&>.vh-article-desc {
flex: 1;
box-sizing: border-box;
padding: 1.188rem;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
min-height: max-content;
overflow: hidden;
&>header { &>header {
box-sizing: border-box;
padding: 0.88rem 1.166rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.36rem; gap: 0.66rem;
width: 100%;
height: max-content;
&>h3 {
display: flex;
align-self: center;
justify-content: space-between;
width: 100%;
height: max-content;
&>.vh-article-cat { &>.vh-article-cat {
flex-shrink: 0;
box-sizing: border-box; box-sizing: border-box;
width: max-content; width: max-content;
font-size: 0.875rem; font-size: 0.875rem;
@ -171,27 +162,73 @@
} }
} }
&>time {
box-sizing: border-box;
margin-top: auto;
font-size: 0.805rem;
font-weight: 400;
color: var(--vh-font-color);
width: max-content;
}
}
&>.title { &>.title {
box-sizing: border-box;
width: 100%;
height: max-content;
overflow: hidden;
&>a {
font-size: 1.06rem; font-size: 1.06rem;
font-weight: 600; font-weight: 600;
line-height: 1.36; transition: color 0.18s;
&:hover {
color: var(--vh-main-color);
}
}
} }
} }
&>.vh-article-excerpt { &>.vh-article-excerpt {
margin: 0.88rem 0; box-sizing: border-box;
padding: 0 1.166rem;
width: 100%; width: 100%;
height: max-content; height: max-content;
color: var(--vh-font-66); color: var(--vh-font-66);
font-size: 0.805rem; font-size: 0.805rem;
font-weight: 400;
letter-spacing: 0.88px; letter-spacing: 0.88px;
line-height: 1.28rem; line-height: 1.28rem;
} }
&>footer {
&>.vh-article-taglist {
margin-top: auto; margin-top: auto;
font-size: 0.805rem; box-sizing: border-box;
color: var(--vh-font-color); padding: 0.66rem 1.166rem 1rem;
width: 100%;
height: max-content;
overflow: hidden;
&>a {
box-sizing: border-box;
margin-right: 0.88rem;
color: var(--vh-font);
font-size: 0.688rem;
font-weight: 400;
transition: color 0.18s;
&:hover {
color: var(--vh-main-color);
}
&::before {
content: "#";
}
&:nth-last-of-type(1) {
margin-right: 0;
} }
} }
} }

View File

@ -13,7 +13,7 @@ import { getCategories, getTags, getRecommendArticles, getCountInfo } from "@/ut
// 分类列表 // 分类列表
const categories = getCategories(); const categories = getCategories();
// 热门标签 // 热门标签
const tags = getTags().slice(0, 16); const tags = getTags();
// 获取网站统计数据 // 获取网站统计数据
const CountInfo = getCountInfo(); const CountInfo = getCountInfo();
// 最新文章 // 最新文章

View File

@ -138,11 +138,11 @@ aside.vh-aside {
&>.count { &>.count {
box-sizing: border-box; box-sizing: border-box;
padding: 1rem 0 0; padding: 0.88rem 0 0.66rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
gap: 0.66rem; gap: 0.28rem;
text-align: center; text-align: center;
background: var(--vh-white-color); background: var(--vh-white-color);
border-radius: var(--vh-main-radius); border-radius: var(--vh-main-radius);
@ -269,7 +269,9 @@ aside.vh-aside {
gap: 0.68rem 1rem; gap: 0.68rem 1rem;
width: 100%; width: 100%;
height: max-content; height: max-content;
overflow: hidden; max-height: 18.88rem;
overflow-x: hidden;
overflow-y: auto;
&>a { &>a {
display: flex; display: flex;

View File

@ -11,7 +11,7 @@ const SiteCover = Site + Cover;
const WebCover = PageCover || SiteCover; const WebCover = PageCover || SiteCover;
// Schema.org 结构化数据JSON-LD // Schema.org 结构化数据JSON-LD
const WebSiteData = { "@context": "https://schema.org", "@type": "WebSite", name: WebTitle, url: canonicalURL, image: { "@type": "ImageObject", url: SiteCover } }; const WebSiteData = { "@context": "https://schema.org", "@type": "WebSite", name: WebTitle, url: canonicalURL, image: { "@type": "ImageObject", url: SiteCover } };
const ArticleData = { "@context": "https://schema.org", "@type": "BlogPosting", mainEntityOfPage: { "@type": "WebPage", "@id": canonicalURL }, headline: WebTitle, image: [WebCover], author: { "@type": "Person", name: Author, url: Site }, publisher: { "@type": "Organization", name: SiteName, logo: { "@type": "ImageObject", url: SiteCover } } }; const ArticleData = { "@context": "https://schema.org", "@type": "BlogPosting", headline: WebTitle, image: [WebCover], author: { "@type": "Person", name: Author, url: Site }, publisher: { "@type": "Organization", name: SiteName, logo: { "@type": "ImageObject", url: SiteCover } } };
// 基础 样式 // 基础 样式
import "@/styles/Base.less"; import "@/styles/Base.less";
--- ---

View File

@ -3,8 +3,6 @@ const { frontmatter } = Astro.props;
// 页面 Info // 页面 Info
import SITE_CONFIG from "@/config"; import SITE_CONFIG from "@/config";
const { Description, Title } = SITE_CONFIG; const { Description, Title } = SITE_CONFIG;
// Aside组件
import Aside from "@/components/Aside/Aside.astro";
// 公共 Layout // 公共 Layout
import Layout from "@/layouts/Layout/Layout.astro"; import Layout from "@/layouts/Layout/Layout.astro";
// 评论组件 // 评论组件

View File

@ -3,8 +3,6 @@ const { frontmatter } = Astro.props;
// 页面 Info // 页面 Info
import SITE_CONFIG from "@/config"; import SITE_CONFIG from "@/config";
const { Description, Title } = SITE_CONFIG; const { Description, Title } = SITE_CONFIG;
// Aside组件
import Aside from "@/components/Aside/Aside.astro";
// 公共 Layout // 公共 Layout
import Layout from "@/layouts/Layout/Layout.astro"; import Layout from "@/layouts/Layout/Layout.astro";
// 评论组件 // 评论组件

View File

@ -7,8 +7,6 @@ import SITE_CONFIG from "@/config";
const { Description } = SITE_CONFIG; const { Description } = SITE_CONFIG;
// 公共 Layout // 公共 Layout
import Layout from "@/layouts/Layout/Layout.astro"; import Layout from "@/layouts/Layout/Layout.astro";
// Aside组件
import Aside from "@/components/Aside/Aside.astro";
// 文章列表组件 // 文章列表组件
import Archive from "@/components/Archive/Archive.astro"; import Archive from "@/components/Archive/Archive.astro";
--- ---

View File

@ -15,8 +15,6 @@ import SITE_CONFIG from "@/config";
const { Description } = SITE_CONFIG; const { Description } = SITE_CONFIG;
// 公共 Layout // 公共 Layout
import Layout from "@/layouts/Layout/Layout.astro"; import Layout from "@/layouts/Layout/Layout.astro";
// Aside组件
import Aside from "@/components/Aside/Aside.astro";
// 文章列表组件 // 文章列表组件
import Archive from "@/components/Archive/Archive.astro"; import Archive from "@/components/Archive/Archive.astro";
--- ---

View File

@ -1,3 +1,11 @@
/*
* @Author: Han
* @Date: 2025-04-07 11:31:34
* @LastEditors: Han
* @LastEditTime: 2025-04-21 14:32:19
* @Description:
*
*/
import SITE_INFO from "@/config"; import SITE_INFO from "@/config";
import { LoadScript } from "@/utils/index"; import { LoadScript } from "@/utils/index";
declare const twikoo: any; declare const twikoo: any;
@ -25,6 +33,7 @@ const WalineFn = async (commentDOM: string, walineInit: any) => {
"https://registry.npmmirror.com/@waline/emojis/1.3.0/files/tieba/tieba_awkward.png", "https://registry.npmmirror.com/@waline/emojis/1.3.0/files/tieba/tieba_awkward.png",
"https://registry.npmmirror.com/@waline/emojis/1.3.0/files/tieba/tieba_sleep.png", "https://registry.npmmirror.com/@waline/emojis/1.3.0/files/tieba/tieba_sleep.png",
], ],
requiredMeta: ['nick', 'mail'],
imageUploader: async (file: any) => { imageUploader: async (file: any) => {
const body = new FormData(); const body = new FormData();
body.append('file', file); body.append('file', file);

View File

@ -25,10 +25,15 @@ article.vh-article-main {
} }
&>.article-meta { &>.article-meta {
box-sizing: border-box;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.88rem; gap: 0.88rem;
font-size: 0.85rem; font-size: 0.85rem;
width: 100%;
height: 0.98rem;
overflow: hidden;
&>.article-meta-item { &>.article-meta-item {
display: flex; display: flex;
@ -40,6 +45,7 @@ article.vh-article-main {
flex-shrink: 0; flex-shrink: 0;
height: 0.888rem; height: 0.888rem;
width: auto; width: auto;
object-fit: contain;
} }
&>time { &>time {

View File

@ -50,8 +50,6 @@
// 隐藏滚动条 // 隐藏滚动条
scrollbar-width: none; scrollbar-width: none;
-ms-overflow-style: none; -ms-overflow-style: none;
// 平滑滚动
scroll-behavior: smooth;
// 去除下划线 // 去除下划线
text-decoration: none; text-decoration: none;
// 消除边框 // 消除边框

View File

@ -25,7 +25,7 @@ const getCategoriesList = async (categories: string) => {
// 获取标签下的文章列表 // 获取标签下的文章列表
const getTagsList = async (tags: string) => { const getTagsList = async (tags: string) => {
const posts = await getCollection("blog"); const posts = await getCollection("blog");
const articleList = posts.filter((i: any) => (i.data.tags || []).includes(tags)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());; const articleList = posts.filter((i: any) => (i.data.tags || []).map((_i: any) => (String(_i))).includes(tags)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
return fmtArticleList(articleList); return fmtArticleList(articleList);
} }