Skip to content

Commit 49186f5

Browse files
committed
feat: 添加日记栏
1 parent 9a1e414 commit 49186f5

24 files changed

Lines changed: 510 additions & 6 deletions

src/components/NoteCard.astro

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
---
2+
import type { CollectionEntry } from "astro:content";
3+
import { Icon } from "astro-icon/components";
4+
import I18nKey from "@i18n/i18nKey";
5+
import { i18n } from "@i18n/translation";
6+
import Markdown from "@components/misc/Markdown.astro";
7+
import { formatDateToYYYYMMDD } from "@utils/date-utils";
8+
9+
interface Props {
10+
class?: string;
11+
entry: CollectionEntry<"notes">;
12+
style?: string;
13+
}
14+
15+
const { entry, style = "" } = Astro.props;
16+
const className = Astro.props.class;
17+
18+
const noteTitle =
19+
(entry.data.title && entry.data.title.trim()) || i18n(I18nKey.untitled);
20+
21+
const { Content } = await entry.render();
22+
---
23+
24+
<div
25+
class:list={[
26+
"card-base note-card w-full rounded-[var(--radius-large)] overflow-hidden transition",
27+
className,
28+
]}
29+
style={style}
30+
>
31+
<div class="note-card__inner">
32+
<div class="note-card__header">
33+
<div class="note-card__title">
34+
<span class="note-card__icon">
35+
<Icon name="material-symbols:edit-note-rounded" />
36+
</span>
37+
<span class="note-card__heading">{noteTitle}</span>
38+
{entry.data.pinned && (
39+
<span class="note-pin-badge">
40+
<Icon name="material-symbols:push-pin" class="note-pin-badge__icon" />
41+
<span>{i18n(I18nKey.pinned)}</span>
42+
</span>
43+
)}
44+
</div>
45+
<div class="note-card__meta">
46+
<span class="note-card__meta-item">
47+
<Icon name="material-symbols:calendar-clock" />
48+
{formatDateToYYYYMMDD(entry.data.published)}
49+
</span>
50+
{entry.data.updated &&
51+
entry.data.updated.getTime() !== entry.data.published.getTime() && (
52+
<span class="note-card__meta-item note-card__meta-item--updated">
53+
<Icon name="material-symbols:history" />
54+
{formatDateToYYYYMMDD(entry.data.updated)}
55+
</span>
56+
)}
57+
</div>
58+
</div>
59+
60+
<div class="note-card__body" data-pagefind-body>
61+
<div class="note-card__body-frame">
62+
<div class="note-card__body-content max-h-[22rem] overflow-y-auto">
63+
<Markdown class="text-sm md:text-base">
64+
<Content />
65+
</Markdown>
66+
</div>
67+
</div>
68+
</div>
69+
</div>
70+
</div>
71+
72+
<style>
73+
.note-card {
74+
position: relative;
75+
background: var(--card-bg);
76+
border: 1px solid color-mix(in srgb, var(--primary) 16%, var(--card-bg));
77+
box-shadow: 0 12px 28px -24px rgba(0, 0, 0, 0.55);
78+
}
79+
80+
.note-card__inner {
81+
position: relative;
82+
display: flex;
83+
flex-direction: column;
84+
gap: 1.25rem;
85+
padding: 1.6rem clamp(1.5rem, 2vw, 2.25rem);
86+
}
87+
88+
.note-card__header {
89+
display: flex;
90+
flex-direction: column;
91+
gap: 0.6rem;
92+
}
93+
94+
@media (min-width: 768px) {
95+
.note-card__header {
96+
flex-direction: row;
97+
justify-content: space-between;
98+
align-items: flex-start;
99+
}
100+
}
101+
102+
.note-card__title {
103+
display: inline-flex;
104+
align-items: center;
105+
gap: 0.65rem;
106+
flex-wrap: wrap;
107+
}
108+
109+
.note-card__icon {
110+
display: inline-flex;
111+
align-items: center;
112+
justify-content: center;
113+
height: 2.15rem;
114+
width: 2.15rem;
115+
border-radius: 0.75rem;
116+
background: color-mix(in srgb, var(--primary) 14%, transparent);
117+
color: color-mix(in srgb, var(--primary) 85%, white 15%);
118+
}
119+
120+
.note-card__icon :global(svg) {
121+
font-size: 1.4rem;
122+
}
123+
124+
.note-card__heading {
125+
font-size: clamp(1.1rem, 1.4vw + 1rem, 1.5rem);
126+
font-weight: 600;
127+
color: color-mix(in srgb, var(--foreground, var(--primary)) 85%, transparent);
128+
}
129+
130+
.note-card__meta {
131+
display: inline-flex;
132+
align-items: center;
133+
gap: 0.75rem;
134+
font-size: 0.85rem;
135+
color: color-mix(in srgb, var(--foreground, var(--primary)) 70%, white 15%);
136+
}
137+
138+
.note-card__meta-item {
139+
display: inline-flex;
140+
align-items: center;
141+
gap: 0.35rem;
142+
padding: 0.3rem 0.65rem;
143+
border-radius: 9999px;
144+
background: color-mix(in srgb, var(--primary) 12%, transparent);
145+
border: 1px solid color-mix(in srgb, var(--primary) 22%, transparent);
146+
}
147+
148+
.note-card__meta-item--updated {
149+
background: color-mix(in srgb, var(--primary) 7%, transparent);
150+
}
151+
152+
.note-card__meta-item :global(svg) {
153+
font-size: 1rem;
154+
}
155+
156+
:global(.dark) .note-card__meta {
157+
color: color-mix(in srgb, white 80%, transparent);
158+
}
159+
160+
:global(.dark) .note-card__meta-item {
161+
background: color-mix(in srgb, white 12%, transparent);
162+
border-color: color-mix(in srgb, white 22%, transparent);
163+
color: color-mix(in srgb, white 85%, transparent);
164+
}
165+
166+
.note-card__body {
167+
position: relative;
168+
}
169+
170+
.note-card__body-frame {
171+
position: relative;
172+
padding: 0.95rem 1.15rem;
173+
border-radius: 1.15rem;
174+
background: color-mix(in srgb, var(--card-bg) 65%, color-mix(in srgb, var(--primary) 30%, white 5%));
175+
border: 1px solid color-mix(in srgb, var(--primary) 20%, transparent);
176+
box-shadow:
177+
inset 0 0 0 1px color-mix(in srgb, var(--primary) 10%, transparent),
178+
0 6px 18px -18px rgba(0, 0, 0, 0.55);
179+
}
180+
181+
.note-card__body-content {
182+
position: relative;
183+
padding-right: 0.35rem;
184+
}
185+
186+
.note-card__body-content::-webkit-scrollbar {
187+
width: 6px;
188+
}
189+
190+
.note-card__body-content::-webkit-scrollbar-thumb {
191+
background-color: color-mix(in srgb, var(--primary) 45%, transparent);
192+
border-radius: 9999px;
193+
}
194+
195+
.note-pin-badge {
196+
display: inline-flex;
197+
align-items: center;
198+
gap: 0.25rem;
199+
background: color-mix(in srgb, var(--primary) 15%, transparent);
200+
color: var(--primary);
201+
font-size: 0.625rem;
202+
font-weight: 600;
203+
padding: 0.15rem 0.5rem;
204+
border-radius: 9999px;
205+
text-transform: uppercase;
206+
letter-spacing: 0.05em;
207+
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--primary) 35%, transparent);
208+
}
209+
210+
.note-pin-badge__icon {
211+
font-size: 0.85rem;
212+
}
213+
</style>

src/components/NoteList.astro

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
import type { CollectionEntry } from "astro:content";
3+
import NoteCard from "./NoteCard.astro";
4+
5+
const { page } = Astro.props;
6+
7+
let delay = 0;
8+
const interval = 40;
9+
---
10+
11+
<div class="flex flex-col gap-4 mb-4">
12+
{page.data.map((entry: CollectionEntry<"notes">) => (
13+
<NoteCard
14+
entry={entry}
15+
class:list="onload-animation"
16+
style={`animation-delay: calc(var(--content-delay) + ${delay++ * interval}ms);`}
17+
/>
18+
))}
19+
</div>

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export const siteConfig: SiteConfig = {
4242
export const navBarConfig: NavBarConfig = {
4343
links: [
4444
LinkPreset.Home,
45+
LinkPreset.Notes,
4546
LinkPreset.Archive,
4647
LinkPreset.About,
4748
LinkPreset.Friends,

src/constants/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const PAGE_SIZE = 8;
2+
export const NOTES_PAGE_SIZE = 12;
23

34
export const LIGHT_MODE = "light",
45
DARK_MODE = "dark",

src/constants/link-presets.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ export const LinkPresets: { [key in LinkPreset]: NavBarLink } = {
77
name: i18n(I18nKey.home),
88
url: "/",
99
},
10-
[LinkPreset.About]: {
11-
name: i18n(I18nKey.about),
12-
url: "/about/",
13-
},
1410
[LinkPreset.Archive]: {
1511
name: i18n(I18nKey.archive),
1612
url: "/archive/",
1713
},
14+
[LinkPreset.Notes]: {
15+
name: i18n(I18nKey.notes),
16+
url: "/notes/",
17+
},
18+
[LinkPreset.About]: {
19+
name: i18n(I18nKey.about),
20+
url: "/about/",
21+
},
1822
[LinkPreset.Friends]: {
1923
name: i18n(I18nKey.friends),
2024
url: "/friends/",

src/content/config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,25 @@ const postsCollection = defineCollection({
1919
nextSlug: z.string().default(""),
2020
}),
2121
});
22+
const notesCollection = defineCollection({
23+
schema: z.object({
24+
title: z.string().optional().default(""),
25+
published: z.date(),
26+
updated: z.date().optional(),
27+
draft: z.boolean().optional().default(false),
28+
lang: z.string().optional().default(""),
29+
pinned: z.boolean().optional().default(false),
30+
prevTitle: z.string().default(""),
31+
prevSlug: z.string().default(""),
32+
nextTitle: z.string().default(""),
33+
nextSlug: z.string().default(""),
34+
}),
35+
});
2236
const specCollection = defineCollection({
2337
schema: z.object({}),
2438
});
2539
export const collections = {
2640
posts: postsCollection,
41+
notes: notesCollection,
2742
spec: specCollection,
2843
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: "小记一条"
3+
published: 2025-11-05
4+
lang: "zh_CN"
5+
pinned: false
6+
---
7+
8+
用 codex 在 Fuwari 主题的基础上弄了个日记卡片,看着还行。
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: "第一条小记"
3+
published: 2025-11-05
4+
lang: "zh_CN"
5+
pinned: true
6+
---
7+
8+
这里当个类似日记的东西,方便记录。

src/i18n/i18nKey.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ enum I18nKey {
22
home = "home",
33
about = "about",
44
archive = "archive",
5+
notes = "notes",
56
search = "search",
67

78
tags = "tags",
@@ -13,6 +14,7 @@ enum I18nKey {
1314
untitled = "untitled",
1415
uncategorized = "uncategorized",
1516
noTags = "noTags",
17+
pinned = "pinned",
1618

1719
wordCount = "wordCount",
1820
wordsCount = "wordsCount",

src/i18n/languages/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const en: Translation = {
55
[Key.home]: "Home",
66
[Key.about]: "About",
77
[Key.archive]: "Archive",
8+
[Key.notes]: "Notes",
89
[Key.search]: "Search",
910

1011
[Key.tags]: "Tags",
@@ -16,6 +17,7 @@ export const en: Translation = {
1617
[Key.untitled]: "Untitled",
1718
[Key.uncategorized]: "Uncategorized",
1819
[Key.noTags]: "No Tags",
20+
[Key.pinned]: "Pinned",
1921

2022
[Key.wordCount]: "word",
2123
[Key.wordsCount]: "words",

0 commit comments

Comments
 (0)