refactor: 移除灵感组件并优化文章卡片布局

- 删除灵感组件及相关数据文件
- 重构文章卡片布局,移除移动端特定样式
- 统一文章统计信息显示方式
- 简化文章卡片交互元素
This commit is contained in:
二叉树树
2025-12-09 18:03:17 +08:00
parent 3bec260b71
commit ee5d021b3b
7 changed files with 20 additions and 140 deletions

View File

@@ -42,14 +42,14 @@ const coverWidth = "28%";
const { remarkPluginFrontmatter } = await entry.render(); const { remarkPluginFrontmatter } = await entry.render();
--- ---
<div class:list={["card-base flex flex-col-reverse md:flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]} style={style}> <div class:list={["card-base flex flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]} style={style}>
<div class:list={["pl-6 md:pl-9 pr-6 md:pr-2 pt-6 md:pt-7 pb-6 relative", {"w-full md:w-[calc(100%_-_52px_-_12px)]": !hasCover, "w-full md:w-[calc(100%_-_var(--coverWidth)_-_12px)]": hasCover}]}> <div class:list={["pl-9 pr-2 pt-6 pb-6 relative", {"w-[calc(100%_-_52px_-_12px)]": !hasCover, "w-[calc(100%_-_var(--coverWidth)_-_12px)]": hasCover}]}>
<a href={url} <a href={url}
class="transition group w-full block font-bold mb-3 text-3xl text-90 class="transition group w-full block font-bold mb-2 md:mb-3 text-xl md:text-3xl text-90
hover:text-[var(--primary)] dark:hover:text-[var(--primary)] hover:text-[var(--primary)] dark:hover:text-[var(--primary)]
active:text-[var(--title-active)] dark:active:text-[var(--title-active)] active:text-[var(--title-active)] dark:active:text-[var(--title-active)]
before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)] before:w-1 before:h-5 before:rounded-md before:bg-[var(--primary)]
before:absolute before:top-[35px] before:left-[18px] before:hidden md:before:block before:absolute before:top-[28px] md:before:top-[32px] before:left-[18px] before:block
"> ">
{isPinned && ( {isPinned && (
<span class="inline-flex items-center mr-2 px-2 py-0.5 text-sm font-medium bg-[oklch(95%_0.2_var(--hue))] dark:bg-[oklch(25%_0.2_var(--hue))] text-[oklch(55%_0.2_var(--hue))] dark:text-[oklch(85%_0.2_var(--hue))] rounded"> <span class="inline-flex items-center mr-2 px-2 py-0.5 text-sm font-medium bg-[oklch(95%_0.2_var(--hue))] dark:bg-[oklch(25%_0.2_var(--hue))] text-[oklch(55%_0.2_var(--hue))] dark:text-[oklch(85%_0.2_var(--hue))] rounded">
@@ -57,15 +57,14 @@ const { remarkPluginFrontmatter } = await entry.render();
</span> </span>
)} )}
{title} {title}
<Icon class="inline text-[2rem] text-[var(--primary)] md:hidden translate-y-0.5 absolute" name="material-symbols:chevron-right-rounded" ></Icon> <Icon class="text-[var(--primary)] text-[2rem] transition inline absolute translate-y-0.5 opacity-0 group-hover:opacity-100 -translate-x-1 group-hover:translate-x-0" name="material-symbols:chevron-right-rounded"></Icon>
<Icon class="text-[var(--primary)] text-[2rem] transition hidden md:inline absolute translate-y-0.5 opacity-0 group-hover:opacity-100 -translate-x-1 group-hover:translate-x-0" name="material-symbols:chevron-right-rounded"></Icon>
</a> </a>
<!-- metadata --> <!-- metadata -->
<PostMetadata published={published} updated={updated} tags={tags} hideTagsForMobile={true} hideUpdateDate={true} class="mb-4"></PostMetadata> <PostMetadata published={published} updated={updated} tags={tags} hideTagsForMobile={true} hideUpdateDate={true} slug={entry.slug} class="mb-2 md:mb-4"></PostMetadata>
<!-- description --> <!-- description -->
<div class:list={["transition text-75 mb-3.5 pr-4", {"line-clamp-2 md:line-clamp-1": !description}]}> <div class:list={["transition text-75 mb-3.5 pr-4 line-clamp-1 md:line-clamp-2"]}>
{ description || remarkPluginFrontmatter.excerpt } { description || remarkPluginFrontmatter.excerpt }
</div> </div>
@@ -74,25 +73,14 @@ const { remarkPluginFrontmatter } = await entry.render();
<div>{remarkPluginFrontmatter.words} 字</div> <div>{remarkPluginFrontmatter.words} 字</div>
<div>|</div> <div>|</div>
<div>{remarkPluginFrontmatter.minutes} 分钟</div> <div>{remarkPluginFrontmatter.minutes} 分钟</div>
<div>|</div>
<div class="flex items-center gap-2">
<div class="flex items-center gap-1">
<Icon name="material-symbols:visibility-outline" class="text-base" />
<span class="text-50 text-sm font-medium" id={`page-views-${entry.slug}`}>-</span>
</div>
<div class="flex items-center gap-1">
<Icon name="material-symbols:person" class="text-base" />
<span class="text-50 text-sm font-medium" id={`page-visitors-${entry.slug}`}>-</span>
</div>
</div>
</div> </div>
</div> </div>
{hasCover && <a href={url} aria-label={title} {hasCover && <a href={url} aria-label={title}
class:list={["group", class:list={["group",
"max-h-[20vh] md:max-h-none mx-4 mt-4 -mb-2 md:mb-0 md:mx-0 md:mt-0", "max-h-none mx-0 mt-0",
"md:w-[var(--coverWidth)] relative md:absolute md:top-3 md:bottom-3 md:right-3 rounded-xl overflow-hidden active:scale-95" "w-[var(--coverWidth)] absolute top-3 bottom-3 right-3 rounded-xl overflow-hidden active:scale-95"
]} > ]} >
<div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition"></div> <div class="absolute pointer-events-none z-10 w-full h-full group-hover:bg-black/30 group-active:bg-black/50 transition"></div>
<!-- 封面图上的箭头 --> <!-- 封面图上的箭头 -->
@@ -107,7 +95,7 @@ const { remarkPluginFrontmatter } = await entry.render();
</a>} </a>}
{!hasCover && {!hasCover &&
<a href={url} aria-label={title} class="!hidden md:!flex btn-regular w-[3.25rem] <a href={url} aria-label={title} class="!flex btn-regular w-[3.25rem]
absolute right-3 top-3 bottom-3 rounded-xl bg-[var(--enter-btn-bg)] absolute right-3 top-3 bottom-3 rounded-xl bg-[var(--enter-btn-bg)]
hover:bg-[var(--enter-btn-bg-hover)] active:bg-[var(--enter-btn-bg-active)] active:scale-95 hover:bg-[var(--enter-btn-bg-hover)] active:bg-[var(--enter-btn-bg-active)] active:scale-95
"> ">
@@ -117,77 +105,9 @@ const { remarkPluginFrontmatter } = await entry.render();
</a> </a>
} }
</div> </div>
<div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 md:hidden"></div> <div class="transition border-t-[1px] border-dashed mx-6 border-black/10 dark:border-white/[0.15] last:border-t-0 hidden"></div>
<script define:vars={{ entry, umamiConfig}}>
// 获取文章浏览量统计
async function fetchPostCardViews(slug) {
if (!umamiConfig.enable) {
return;
}
try {
// 调用全局工具获取 Umami 分享数据
const { websiteId, token } = await getUmamiShareData(umamiConfig.baseUrl, umamiConfig.shareId);
// 第二步:获取统计数据
const currentTimestamp = Date.now();
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&path=eq.%2Fposts%2F${slug}%2F&compare=false`;
const statsResponse = await fetch(statsUrl, {
headers: {
'x-umami-share-token': token
}
});
if (statsResponse.status === 401) {
clearUmamiShareCache();
return await fetchPostCardViews(slug);
}
if (!statsResponse.ok) {
throw new Error('获取统计数据失败');
}
const statsData = await statsResponse.json();
const pageViews = statsData.pageviews || 0;
const visits = statsData.visitors || 0;
const viewsElement = document.getElementById(`page-views-${slug}`);
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
if (viewsElement) {
viewsElement.textContent = pageViews;
}
if (visitorsElement) {
visitorsElement.textContent = visits;
}
} catch (error) {
console.error('Error fetching page views for', slug, ':', error);
const viewsElement = document.getElementById(`page-views-${slug}`);
const visitorsElement = document.getElementById(`page-visitors-${slug}`);
if (viewsElement) {
viewsElement.textContent = '-';
}
if (visitorsElement) {
visitorsElement.textContent = '-';
}
}
}
// 页面加载完成后获取统计数据
function initPostCardStats() {
const slug = entry.slug;
if (slug) {
fetchPostCardViews(slug);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initPostCardStats);
} else {
initPostCardStats();
}
</script>
<style define:vars={{coverWidth}}> <style define:vars={{coverWidth}}>
</style> </style>

View File

@@ -72,13 +72,13 @@ const className = Astro.props.class;
<div class="meta-icon"> <div class="meta-icon">
<Icon name="material-symbols:visibility-outline-rounded" class="text-xl"></Icon> <Icon name="material-symbols:visibility-outline-rounded" class="text-xl"></Icon>
</div> </div>
<span class="text-50 text-sm font-medium" id="page-views-display">-</span> <span class="text-50 text-sm font-medium" id={`page-views-${slug}`}>-</span>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<div class="meta-icon"> <div class="meta-icon">
<Icon name="material-symbols:person" class="text-xl"></Icon> <Icon name="material-symbols:person" class="text-xl"></Icon>
</div> </div>
<span class="text-50 text-sm font-medium" id="page-visitors-display">-</span> <span class="text-50 text-sm font-medium" id={`page-visitors-${slug}`}>-</span>
</div> </div>
</> </>
)} )}
@@ -119,8 +119,8 @@ const className = Astro.props.class;
const pageViews = statsData.pageviews || 0; const pageViews = statsData.pageviews || 0;
const visits = statsData.visitors || 0; const visits = statsData.visitors || 0;
const viewsElement = document.getElementById('page-views-display'); const viewsElement = document.getElementById(`page-views-${slug}`);
const visitorsElement = document.getElementById('page-visitors-display'); const visitorsElement = document.getElementById(`page-visitors-${slug}`);
if (viewsElement) { if (viewsElement) {
viewsElement.textContent = pageViews; viewsElement.textContent = pageViews;
} }
@@ -129,8 +129,8 @@ const className = Astro.props.class;
} }
} catch (error) { } catch (error) {
console.error('Error fetching page views:', error); console.error('Error fetching page views:', error);
const viewsElement = document.getElementById('page-views-display'); const viewsElement = document.getElementById(`page-views-${slug}`);
const visitorsElement = document.getElementById('page-visitors-display'); const visitorsElement = document.getElementById(`page-visitors-${slug}`);
if (viewsElement) { if (viewsElement) {
viewsElement.textContent = '-'; viewsElement.textContent = '-';
} }

View File

@@ -9,7 +9,7 @@ let delay = 0;
const interval = 50; const interval = 50;
--- ---
<div class="transition flex flex-col rounded-[var(--radius-large)] bg-transparent py-1 md:py-0 md:gap-4 mb-4"> <div class="transition flex flex-col rounded-[var(--radius-large)] bg-transparent gap-4 mb-4">
{page.data.map((entry: CollectionEntry<"posts">) => ( {page.data.map((entry: CollectionEntry<"posts">) => (
<PostCard <PostCard

View File

@@ -1,33 +0,0 @@
---
import WidgetLayout from "./WidgetLayout.astro";
import { Icon } from "astro-icon/components";
import inspirationContent from "@/data/inspiration.txt?raw";
const items = inspirationContent.split('\n').filter(line => line.trim() !== '');
interface Props {
class?: string;
style?: string;
}
const className = Astro.props.class;
const style = Astro.props.style;
---
{items.length > 0 && (
<WidgetLayout name="灵感一刻" id="inspiration-list" class={className} style={style}>
<div class="flex flex-col gap-2">
{items.map((item, index) => (
<div class="flex items-start gap-2 text-sm text-neutral-700 dark:text-neutral-300">
<span class="font-bold text-[var(--primary)] flex-shrink-0 select-none w-5 text-right">{index + 1}.</span>
<span class="leading-5">{item}</span>
</div>
))}
</div>
<div class="mt-4 flex justify-center">
<a href="https://github.com/afoim/fuwari/blob/main/src/data/inspiration.txt" target="_blank" rel="noopener noreferrer" class="btn-plain rounded-lg h-9 px-4 flex items-center gap-2 text-[var(--primary)] text-sm">
<Icon name="material-symbols:edit-square-outline" class="text-lg" />
记录新灵感
</a>
</div>
</WidgetLayout>
)}

View File

@@ -4,7 +4,6 @@ import type { MarkdownHeading } from "astro";
import Profile from "./Profile.astro"; import Profile from "./Profile.astro";
import Tag from "./Tags.astro"; import Tag from "./Tags.astro";
import DomainSwitcher from "./DomainSwitcher.astro"; import DomainSwitcher from "./DomainSwitcher.astro";
import Inspiration from "./Inspiration.astro";
interface Props { interface Props {
class?: string; class?: string;
@@ -20,7 +19,6 @@ const className = Astro.props.class;
<div id="sidebar-sticky" class="transition-all duration-700 flex flex-col w-full gap-4 top-4 sticky top-4"> <div id="sidebar-sticky" class="transition-all duration-700 flex flex-col w-full gap-4 top-4 sticky top-4">
<DomainSwitcher class="onload-animation" style="animation-delay: 150ms"></DomainSwitcher> <DomainSwitcher class="onload-animation" style="animation-delay: 150ms"></DomainSwitcher>
<Tag class="onload-animation" style="animation-delay: 200ms"></Tag> <Tag class="onload-animation" style="animation-delay: 200ms"></Tag>
<Inspiration class="onload-animation" style="animation-delay: 250ms"></Inspiration>
<!-- 赞助标 --> <!-- 赞助标 -->
<div class="overflow-hidden flex justify-center"> <div class="overflow-hidden flex justify-center">
<a href="https://secbit.ai/" target="_blank" rel="noopener noreferrer"> <a href="https://secbit.ai/" target="_blank" rel="noopener noreferrer">

View File

@@ -1,5 +0,0 @@
教你用OBSAV1编码录制
教你配置Cloudflare Turnstile
博客开发日志
OneDrive Index搭建随时随地存取文件
Rybbit网站统计搭建教程

View File

@@ -45,7 +45,7 @@ const mainPanelTop = siteConfig.banner.enable
<!-- Navbar --> <!-- Navbar -->
<slot slot="head" name="head"></slot> <slot slot="head" name="head"></slot>
<div id="top-row" class="z-50 pointer-events-none relative transition-all duration-700 max-w-[var(--page-width)] px-0 md:px-4 mx-auto" class:list={[""]}> <div id="top-row" class="z-50 pointer-events-none relative transition-all duration-700 max-w-[var(--page-width)] px-4 md:px-4 mx-auto" class:list={[""]}>
<div id="navbar-wrapper" class="pointer-events-auto sticky top-0 transition-all"> <div id="navbar-wrapper" class="pointer-events-auto sticky top-0 transition-all">
<Navbar></Navbar> <Navbar></Navbar>
</div> </div>
@@ -64,7 +64,7 @@ const mainPanelTop = siteConfig.banner.enable
<!-- The pointer-events-none here prevent blocking the click event of the TOC --> <!-- The pointer-events-none here prevent blocking the click event of the TOC -->
<div class="relative max-w-[var(--page-width)] mx-auto pointer-events-auto"> <div class="relative max-w-[var(--page-width)] mx-auto pointer-events-auto">
<div id="main-grid" class="transition duration-700 w-full left-0 right-0 grid grid-cols-[17.5rem_auto] grid-rows-[auto_1fr_auto] lg:grid-rows-[auto] <div id="main-grid" class="transition duration-700 w-full left-0 right-0 grid grid-cols-[17.5rem_auto] grid-rows-[auto_1fr_auto] lg:grid-rows-[auto]
mx-auto gap-4 px-0 md:px-4" mx-auto gap-4 px-4 md:px-4"
> >
<!-- Banner image credit --> <!-- Banner image credit -->
{hasBannerCredit && <a href={siteConfig.banner.credit.url} id="banner-credit" target="_blank" rel="noopener" aria-label="Visit image source" {hasBannerCredit && <a href={siteConfig.banner.credit.url} id="banner-credit" target="_blank" rel="noopener" aria-label="Visit image source"