feat(pages): 五页型落地——首页/文章双模板/图库 masonry/瞬间/关于
- 首页:名片+身份陈述空槽+按年分组分轨列表(情绪色/mono标签)+影像格+项目墙
- 文章 /archives/{slug}(与 Halo 旧 URL 1:1):reading→衬线纸墨 / tech→
TOC 侧栏(≥1120 sticky)+2px 进度条+Artalk 容器占位
- 图库:grid masonry(构建期 aspect-ratio 零 JS)+原生 dialog lightbox
(←→/Esc+EXIF 底栏)+分组筛选
- 瞬间时间线 / 关于(三轨版图+构建说明)
- sharp ^0.35.5 入依赖(Astro 7 不内置,astro:assets 缩略图管线前提)
- 裸 blockquote 默认吃 A 墨线样式(markdown 原生输出无类名的缝隙)
- 车道 30min 超时,产物完整,主会话补 sharp+断言脚本递归修正后收编
验证: pnpm astro build exit 0(7 页);五路由产物断言过;
scripts/check-responsive.sh 11/11 ok(1120/820/760/560 全档)
Spec: 2026-10-24_add-blog-skeleton
Co-authored-by: GLM-5.3
This commit is contained in:
1 parent
80ff67e8fa
commit
945a9ee610
14 files changed
+1281
-18
No files matched your search
@@ -0,0 +1,42 @@
|
||||
---
|
||||
// 名片头像占位:内联 SVG 渐变 60px;真实头像接入后整体替换本组件即可
|
||||
---
|
||||
|
||||
<svg
|
||||
class="avatar"
|
||||
viewBox="0 0 60 60"
|
||||
width="60"
|
||||
height="60"
|
||||
role="img"
|
||||
aria-label="头像占位"
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="avatar-grad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="var(--mood-3)"></stop>
|
||||
<stop offset="1" stop-color="var(--accent)"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="60" height="60" rx="14" fill="url(#avatar-grad)"></rect>
|
||||
<circle cx="44" cy="15" r="10" fill="#fff" opacity=".25"></circle>
|
||||
<path d="M0 46 20 28 34 40 46 32 60 46 60 60 0 60Z" fill="#000" opacity=".14"></path>
|
||||
<text
|
||||
x="30"
|
||||
y="38"
|
||||
text-anchor="middle"
|
||||
font-size="16"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
opacity=".92"
|
||||
font-family="var(--font-mono)"
|
||||
>
|
||||
w4
|
||||
</text>
|
||||
</svg>
|
||||
|
||||
<style>
|
||||
.avatar {
|
||||
flex: none;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
// 名片区(首页/关于共用):渐变头像占位 + 称呼;图标行等内容由使用页经 slot 注入
|
||||
import Avatar from './Avatar.astro';
|
||||
---
|
||||
|
||||
<div class="idcard">
|
||||
<Avatar />
|
||||
<div class="idcard-main">
|
||||
<p class="idcard-name">wait4x</p>
|
||||
<!-- 身份陈述:用户后续撰写(一句话自我介绍,落在称呼下方) -->
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.idcard {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-4);
|
||||
margin-block: var(--space-5);
|
||||
}
|
||||
.idcard-name {
|
||||
font-size: 21px;
|
||||
font-weight: 700;
|
||||
color: var(--ink-1);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,137 @@
|
||||
---
|
||||
// 年份分组 + 轨道分节的文章列表(首页与 /archives/ 共用)
|
||||
// 轨道标签单一事实源:content.config 的 POST_TRACKS,此处不另立词表
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
import { POST_TRACKS, trackOf, type PostCategory } from '../content.config';
|
||||
|
||||
interface Props {
|
||||
/** 调用方已完成 draft 过滤与 pubDate 倒序 */
|
||||
posts: CollectionEntry<'posts'>[];
|
||||
}
|
||||
const { posts } = Astro.props;
|
||||
|
||||
const byYear = new Map<number, CollectionEntry<'posts'>[]>();
|
||||
for (const post of posts) {
|
||||
const year = post.data.pubDate.getUTCFullYear();
|
||||
const bucket = byYear.get(year);
|
||||
if (bucket) bucket.push(post);
|
||||
else byYear.set(year, [post]);
|
||||
}
|
||||
const mmdd = (d: Date) =>
|
||||
`${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;
|
||||
---
|
||||
|
||||
<div class="post-list">
|
||||
{[...byYear.entries()].map(([year, list]) => (
|
||||
<section class="year-block" aria-label={`${year} 年文章`}>
|
||||
<h2 class="year">{year}</h2>
|
||||
{(Object.keys(POST_TRACKS) as PostCategory[]).map((cat) => {
|
||||
const rows = list.filter((post) => post.data.category === cat);
|
||||
if (rows.length === 0) return null;
|
||||
return (
|
||||
<div class="track-block">
|
||||
<h3 class="track">{trackOf(cat)}</h3>
|
||||
<ul>
|
||||
{rows.map((post) => (
|
||||
<li>
|
||||
<a class="row tap" href={`/archives/${post.id}/`}>
|
||||
{cat === 'reading' && (
|
||||
<i
|
||||
class="emo"
|
||||
style={`background:${post.data.mood ?? 'var(--mood)'}`}
|
||||
title="情绪色"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
<span class="row-title">{post.data.title}</span>
|
||||
{cat !== 'reading' &&
|
||||
post.data.tags.map((tag) => <code class="tag">{`#${tag}`}</code>)}
|
||||
<time class="row-date" datetime={post.data.pubDate.toISOString()}>
|
||||
{mmdd(post.data.pubDate)}
|
||||
</time>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.year-block + .year-block { margin-top: var(--space-5); }
|
||||
.year {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--ink-3);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.track {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
margin: var(--space-3) 0 var(--space-1);
|
||||
font-size: 12.5px;
|
||||
font-weight: 400;
|
||||
color: var(--ink-4);
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
.track::before {
|
||||
content: '';
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 2px;
|
||||
background: var(--ink-4);
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3);
|
||||
width: 100%;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
li:last-child > .row { border-bottom: none; }
|
||||
.emo {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 3px;
|
||||
flex: none;
|
||||
}
|
||||
.row-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 16px;
|
||||
color: var(--ink-2);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
transition: color var(--dur) var(--ease);
|
||||
}
|
||||
.row:hover .row-title { color: var(--accent); }
|
||||
.tag {
|
||||
flex: none;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
color: var(--ink-3);
|
||||
background: var(--bg-soft);
|
||||
border-radius: 5px;
|
||||
padding: 1px 7px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.row-date {
|
||||
flex: none;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 13px;
|
||||
color: var(--ink-4);
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user