mirror of
https://github.com/StepanovPlaton/AboutMe.git
synced 2026-04-04 12:50:49 +04:00
Initial commit
This commit is contained in:
114
src/pages/friends.astro
Normal file
114
src/pages/friends.astro
Normal file
@@ -0,0 +1,114 @@
|
||||
---
|
||||
import { getEntry, render } from "astro:content";
|
||||
|
||||
import { LinkPresets } from "@constants/link-presets";
|
||||
import { LinkPreset } from "@/types/config";
|
||||
import { friendsData } from "@utils/friends";
|
||||
import Markdown from "@components/common/markdown.astro";
|
||||
import GridLayout from "@layouts/grid.astro";
|
||||
import BackwardButton from "@components/backwardButton.astro";
|
||||
|
||||
|
||||
const pageTitle = LinkPresets[LinkPreset.Friends].name;
|
||||
const pageDescription = LinkPresets[LinkPreset.Friends].description;
|
||||
|
||||
const friendsPost = await getEntry("spec", "friends");
|
||||
|
||||
if (!friendsPost) {
|
||||
throw new Error("friends page content not found");
|
||||
}
|
||||
|
||||
const { Content } = await render(friendsPost);
|
||||
const items = friendsData;
|
||||
|
||||
function shuffleArray(array) {
|
||||
const newArray = [...array];
|
||||
for (let i = newArray.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
const shuffledItems = shuffleArray(items);
|
||||
---
|
||||
|
||||
<GridLayout title={pageTitle} description={pageDescription}>
|
||||
<div class="flex w-full rounded-(--radius-large) overflow-hidden relative min-h-32">
|
||||
<div class="card-base z-10 px-9 py-6 relative w-full ">
|
||||
<BackwardButton currentPath={Astro.url.pathname} />
|
||||
<!-- 标题 -->
|
||||
<header class="mb-8">
|
||||
<h1 class="text-3xl font-bold text-neutral-900 dark:text-neutral-100 mb-3">
|
||||
{pageTitle}
|
||||
</h1>
|
||||
{pageDescription && (
|
||||
<p class="text-neutral-600 dark:text-neutral-400">
|
||||
{pageDescription}
|
||||
</p>
|
||||
)}
|
||||
</header>
|
||||
<!-- 链接网格 -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6 my-4">
|
||||
{shuffledItems.map((item) => (
|
||||
<a href={item.siteurl} target="_blank" rel="noopener noreferrer" class="menu-card group flex flex-row items-center p-4 rounded-xl border transition-all duration-300 gap-4">
|
||||
<div class="icon-wrapper w-20 h-20 shrink-0 flex items-center justify-center rounded-full transition-all duration-300 overflow-hidden bg-zinc-200 dark:bg-zinc-900">
|
||||
<img src={item.imgurl} alt={item.title} class="w-full h-full object-cover transition duration-300 group-hover:scale-110" />
|
||||
</div>
|
||||
<div class="flex flex-col justify-center overflow-hidden">
|
||||
<h2 class="text-lg font-bold text-neutral-900 dark:text-neutral-100 group-hover:text-(--primary) transition-colors duration-300 truncate">
|
||||
{item.title}
|
||||
</h2>
|
||||
<p class="text-sm text-neutral-600 dark:text-neutral-400 line-clamp-1 mt-1">
|
||||
{item.desc}
|
||||
</p>
|
||||
{item.tags && item.tags.length > 0 && (
|
||||
<div class="flex flex-wrap gap-1.5 mt-2">
|
||||
{item.tags.slice(0, 2).map((tag) => (
|
||||
<span class="text-[10px] px-2 py-0.5 rounded-full bg-neutral-100 dark:bg-neutral-800 text-neutral-500 dark:text-neutral-400 border border-neutral-200 dark:border-neutral-700">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
{item.tags.length > 2 && (
|
||||
<span class="text-[10px] px-2 py-0.5 text-neutral-400">
|
||||
+{item.tags.length - 2}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<Markdown class="mt-2">
|
||||
<Content />
|
||||
</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</GridLayout>
|
||||
|
||||
<style>
|
||||
.menu-card {
|
||||
cursor: pointer;
|
||||
background-color: none;
|
||||
border-color: var(--line-divider);
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
background-color: color-mix(in oklch, var(--primary), transparent 85%);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.menu-card:hover {
|
||||
background-color: color-mix(in oklch, var(--primary), transparent 95%);
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 20px color-mix(in oklch, var(--primary), transparent 80%);
|
||||
translate: 0 -4px;
|
||||
}
|
||||
|
||||
.menu-card:hover .icon-wrapper {
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
box-shadow: 0 0 15px color-mix(in oklch, var(--primary), transparent 50%);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user