mirror of
https://github.com/KivotosRailway/website.git
synced 2026-11-03 11:06:32 +09:00
初步建设主页和新闻页面
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import type { NewsItem } from "@/data/news";
|
||||
|
||||
export function NewsList({ news }: { news: NewsItem[] }) {
|
||||
const [activeCategory, setActiveCategory] = useState<string | null>(null);
|
||||
const categories = Array.from(new Set(news.map((item) => item.category).filter(Boolean)));
|
||||
const visibleNews = activeCategory
|
||||
? news.filter((item) => item.category === activeCategory)
|
||||
: news;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="news-toolbar" aria-label="新闻筛选和布局控制">
|
||||
<div className="news-toolbar-actions">
|
||||
<button
|
||||
type="button"
|
||||
className={`news-filter-button${activeCategory === null ? " active" : ""}`}
|
||||
onClick={() => setActiveCategory(null)}
|
||||
>
|
||||
全部
|
||||
</button>
|
||||
{categories.map((category) => (
|
||||
<button
|
||||
key={category}
|
||||
type="button"
|
||||
className={`news-filter-button${activeCategory === category ? " active" : ""}`}
|
||||
onClick={() => setActiveCategory(category)}
|
||||
>
|
||||
{category}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="news-toolbar-right">
|
||||
<button type="button" className="news-view-toggle" aria-label="列表视图">☰</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="news-list-grid">
|
||||
{visibleNews.map((item) => (
|
||||
<article key={item.id} className="news-list-card">
|
||||
<Link href={item.href} className="news-list-link">
|
||||
<div className="news-list-cover" style={{ backgroundImage: `url(${item.cover})` }} />
|
||||
<div className="news-list-meta">
|
||||
<span className="news-list-tag">{item.category}</span>
|
||||
<h3>{item.title}</h3>
|
||||
<time dateTime={item.date}>{item.date}</time>
|
||||
</div>
|
||||
</Link>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
export function NewsShare({ title }: { title: string }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const getPageUrl = () => window.location.href;
|
||||
|
||||
const copyLink = async () => {
|
||||
await navigator.clipboard.writeText(getPageUrl());
|
||||
setCopied(true);
|
||||
window.setTimeout(() => setCopied(false), 1600);
|
||||
};
|
||||
|
||||
const shareOnX = () => {
|
||||
const url = encodeURIComponent(getPageUrl());
|
||||
const text = encodeURIComponent(title);
|
||||
window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
||||
const shareOnQq = () => {
|
||||
const url = encodeURIComponent(getPageUrl());
|
||||
const text = encodeURIComponent(title);
|
||||
window.open(`https://connect.qq.com/widget/shareqq/index.html?url=${url}&title=${text}`, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="news-share" aria-labelledby="news-share-title">
|
||||
<h2 id="news-share-title">分享</h2>
|
||||
<div className="news-share-actions">
|
||||
<button type="button" className="news-share-button" onClick={copyLink} aria-label="复制链接">
|
||||
{copied ? "已复制" : "复制链接"}
|
||||
</button>
|
||||
<button type="button" className="news-share-button news-share-x" onClick={shareOnX} aria-label="分享到 X">X</button>
|
||||
<button type="button" className="news-share-button news-share-qq" onClick={shareOnQq} aria-label="分享到 QQ">QQ</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user