diff --git a/src/components/header/HeaderNavigation.tsx b/src/components/header/HeaderNavigation.tsx index 2df2dc1..d896dca 100644 --- a/src/components/header/HeaderNavigation.tsx +++ b/src/components/header/HeaderNavigation.tsx @@ -8,8 +8,8 @@ export default function App() { const menuItems = [ { - link: "/archive", - name: "目录", + link: "/blog", + name: "博客", }, { link: "/calendar", diff --git a/src/consts.ts b/src/consts.ts index 3335637..04572f1 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -3,3 +3,5 @@ export const SITE_EMAIL = "contact@nbtca.space" export const SITE_NAME = "NingboTech University, Computer Association" export const SITE_DESCRIPTION = "Computer Association" export const SITE_URL = import.meta.env.PUBLIC_SITE_URL +export const CA_LOGO_URL = "https://oss.nbtca.space/CA-logo.svg" +export const CA_PUBLIC_ICAL_URL = "https://ical.nbtca.space" diff --git a/src/layouts/MoreTile.astro b/src/layouts/MoreTile.astro index a09fe01..d166571 100644 --- a/src/layouts/MoreTile.astro +++ b/src/layouts/MoreTile.astro @@ -1,10 +1,11 @@ --- +import { CA_LOGO_URL } from "../consts" import { formatDate } from "../utils" const { title, href, cover, tags, date } = Astro.props const dateFormatted = formatDate(date) const type = tags?.[0] ?? "默认" -const image = cover?.url ?? cover ?? "https://oss.nbtca.space/CA-logo.svg" +const image = cover?.url ?? cover ?? CA_LOGO_URL const label = `${title} - ${type} - 发表时间 ${dateFormatted}`; --- diff --git a/src/pages/archive.astro b/src/pages/archive.astro deleted file mode 100644 index 61d9d24..0000000 --- a/src/pages/archive.astro +++ /dev/null @@ -1,43 +0,0 @@ ---- -import BaseLayout from "../layouts/BaseLayout.astro" -import ArchivePostList from "../layouts/ArchivePostList.astro" -const allPosts = await Astro.glob("./posts/*.md") -const Blogs = await Astro.glob("../pages/posts/blogs/**/*.md") -const tags = ["寝室", "技术", "学习", "活动", "其他"] -const posts = [] - -tags.forEach((tag) => { - const filteredPosts = allPosts.filter(post => - post.frontmatter.tags.includes(tag), - ) - const filteredBlogs = Blogs.filter( - post => post.frontmatter.tags?.includes(tag) ?? tag === "其他", - ) - posts.push([...filteredPosts, ...filteredBlogs]) -}) ---- - - - - - { - tags.map((tag, index) => { - return ( - - {tag} - - {posts[index].length !== 0 - ? ( - - ) - : ( - 暂无文章 - )} - - - ) - }) - } - - - diff --git a/src/pages/blog.astro b/src/pages/blog.astro new file mode 100644 index 0000000..b894a80 --- /dev/null +++ b/src/pages/blog.astro @@ -0,0 +1,87 @@ +--- +import BaseLayout from "../layouts/BaseLayout.astro" +import type { MarkdownInstance } from "astro" +import dayjs from "dayjs" +import { CA_LOGO_URL } from "../consts" + +type Cover = { + url: string + square: string + alt: string +} | string + +type Post = { + layout: string + title: string + pubDate: string // ISO 字符串,可选改为 `Date` 类型 + description: string + author: string + cover?: Cover + tags: string[] + theme: string + featured: boolean +} + +const posts: MarkdownInstance[] = await Astro.glob("./posts/*.md") +const blogs: MarkdownInstance[] = await Astro.glob("../pages/posts/blogs/**/*.md") + +const allPosts = [...posts, ...blogs].sort((a, b) => { + return new Date(b.frontmatter.pubDate).getTime() - new Date(a.frontmatter.pubDate).getTime() +}) + +const getCover = (post: MarkdownInstance) => { + if (typeof post.frontmatter.cover === "string") { + return { url: post.frontmatter.cover, square: post.frontmatter.cover, alt: "" } + } + return post.frontmatter.cover || { url: "", square: "", alt: "" } +} + + // const tags = allPosts.reduce((acc, post) => { + // post.frontmatter.tags.forEach(tag => { + // if (!acc.includes(tag)) { + // acc.push(tag) + // } + // }) + // return acc + // }, [] as string[]).sort((a, b) => a.localeCompare(b)) + +--- + + + + + 博客 + + + + + + + + { + allPosts.map((v) => { + return ( + + + + + {v.frontmatter.tags.slice(0, 3).map((tag) => { + return {tag} + })} + + {v.frontmatter.title} + {dayjs(v.frontmatter.pubDate).format("YYYY-MM-DD")} + + + + ) + }) + } + + + + diff --git a/src/pages/calendar/Schedule.tsx b/src/pages/calendar/Schedule.tsx index e7fc3a3..74a6cdd 100644 --- a/src/pages/calendar/Schedule.tsx +++ b/src/pages/calendar/Schedule.tsx @@ -5,6 +5,7 @@ import { Alert, Button, Calendar, Link, Spinner, Select, SelectItem } from "@her import { today, getLocalTimeZone } from "@internationalized/date" import "dayjs/locale/zh-cn" +import { CA_PUBLIC_ICAL_URL } from "../../consts" dayjs.locale("zh-cn") @@ -17,7 +18,7 @@ type ScheduleEvent = { } const parseCal = async (): Promise => { - const res = await fetch("https://ical.nbtca.space/").then(res => res.text()) + const res = await fetch(CA_PUBLIC_ICAL_URL).then(res => res.text()) const jcalData = ICAL.parse(res) return new ICAL.Component(jcalData) } @@ -110,62 +111,6 @@ const expandEventOccurrences = ( return occurrences } -const extractScheduleEvents = (icalComp: ICAL.Component): ScheduleEvent[] => { - const vevents = icalComp.getAllSubcomponents("vevent") - const rangeEnd = ICAL.Time.fromDateString("2026-01-01") - const rangeStart = ICAL.Time.fromDateString("2020-01-01") - - // First, collect all exception events (events with RECURRENCE-ID) - const exceptions = new Map>() // uid -> set of recurrence-id strings - const exceptionEvents: ScheduleEvent[] = [] - - vevents.forEach((vevent) => { - const recurrenceId = vevent.getFirstPropertyValue("recurrence-id") - if (recurrenceId) { - const uid = vevent.getFirstPropertyValue("uid") - const event = new ICAL.Event(vevent) - - // Check if exception is in range - if (event.startDate.compare(rangeEnd) <= 0 && event.endDate.compare(rangeStart) >= 0) { - exceptionEvents.push({ - start: event.startDate.toJSDate(), - end: event.endDate.toJSDate(), - summary: event.summary, - description: event.description, - recurrenceId: recurrenceId.toString(), - }) - } - - // Track exception for filtering recurring events - if (!exceptions.has(uid)) { - exceptions.set(uid, new Set()) - } - exceptions.get(uid)!.add(recurrenceId.toString()) - } - }) - - // Process regular and recurring events - const regularEvents = vevents - .filter(vevent => !vevent.getFirstPropertyValue("recurrence-id")) - .flatMap((vevent) => { - const event = new ICAL.Event(vevent) - if (event.iterator().complete) { - return [{ - start: event.startDate.toJSDate(), - end: event.endDate.toJSDate(), - summary: event.summary, - description: event.description, - recurrenceId: event.uid || event.startDate.toString(), - }] - } - const eventExceptions = exceptions.get(event.uid) || new Set() - return expandEventOccurrences(event, rangeStart, rangeEnd, eventExceptions) - }) - - return [...regularEvents, ...exceptionEvents] - .sort((a, b) => b.start.getTime() - a.start.getTime()) -} - const formatTimePair = (s: Date, e: Date): string => { const start = dayjs(s) const end = dayjs(e) @@ -216,14 +161,6 @@ export default function Schedule() { } }, [focusedDate]) - useEffect(() => { - setLoading(true) - parseCal().then((icalComp) => { - setScheduledEvents(extractScheduleEvents(icalComp)) - setLoading(false) - }) - }, []) - const groupedEvents = useMemo(() => { const grouped = new Map() scheduledEvents.forEach((event) => { @@ -380,7 +317,7 @@ export default function Schedule() { {formatTimePair(event.start, event.end)} { event.description && ( - {event.description} + {event.description} ) } diff --git a/src/pages/index.astro b/src/pages/index.astro index 42697ad..541138a 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -110,10 +110,10 @@ Blogs.sort( 阅读历史文章
{event.description}