初始化:Astro 站点 + Sveltia CMS 后台 + 部署配置
This commit is contained in:
106
src/pages/projects/index.astro
Normal file
106
src/pages/projects/index.astro
Normal file
@@ -0,0 +1,106 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import ProjectCard from '../../components/ProjectCard.astro';
|
||||
|
||||
const projects = (await getCollection('projects')).sort(
|
||||
(a, b) => b.data.order - a.data.order
|
||||
);
|
||||
|
||||
const categories = ['全部', '硬件', '软件', '通信', '机器人', '其他'];
|
||||
---
|
||||
|
||||
<BaseLayout title="项目" description="电子、软件、通信与机器人方向的项目展示">
|
||||
<section class="page-head">
|
||||
<h1>项目</h1>
|
||||
<p class="muted">电子工程、软件、通信与机器人方向的作品与产品。</p>
|
||||
</section>
|
||||
|
||||
{
|
||||
projects.length > 0 ? (
|
||||
<>
|
||||
<div class="filters mono" id="filters">
|
||||
{categories.map((c) => (
|
||||
<button class="filter" data-cat={c}>
|
||||
{c}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div class="grid" id="grid">
|
||||
{projects.map((p) => (
|
||||
<div class="grid-item" data-cat={p.data.category}>
|
||||
<ProjectCard
|
||||
title={p.data.title}
|
||||
description={p.data.description}
|
||||
category={p.data.category}
|
||||
tags={p.data.tags}
|
||||
href={`/projects/${p.id}`}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<p class="muted">
|
||||
暂无项目。在 <code>src/content/projects/</code> 新建 Markdown 文件即可添加。
|
||||
</p>
|
||||
)
|
||||
}
|
||||
</BaseLayout>
|
||||
|
||||
<script>
|
||||
const buttons = document.querySelectorAll<HTMLButtonElement>('.filter');
|
||||
const items = document.querySelectorAll<HTMLElement>('.grid-item');
|
||||
buttons[0]?.classList.add('active');
|
||||
buttons.forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
buttons.forEach((b) => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
const cat = btn.dataset.cat;
|
||||
items.forEach((item) => {
|
||||
item.style.display =
|
||||
cat === '全部' || item.dataset.cat === cat ? '' : 'none';
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page-head {
|
||||
padding: 3rem 0 1.5rem;
|
||||
}
|
||||
.page-head h1 {
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
.filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.filter {
|
||||
background: var(--bg-elev);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-dim);
|
||||
border-radius: 999px;
|
||||
padding: 0.3rem 0.85rem;
|
||||
font-size: 0.8rem;
|
||||
font-family: var(--font-mono);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
.filter:hover {
|
||||
color: var(--text);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
.filter.active {
|
||||
color: var(--accent-strong);
|
||||
border-color: var(--accent-dim);
|
||||
background: rgba(57, 208, 216, 0.1);
|
||||
}
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user