好的,让我们来实现社交媒体分享功能和博客文章归档功能。
第十三部分:实现社交媒体分享功能和博客文章归档
- 首先,让我们添加社交媒体分享功能。我们将使用简单的分享链接,而不是复杂的第三方插件。
更新 src/views/posts/show.eta 文件,在文章内容下方添加分享按钮:
<% layout('../layouts/main.eta', { title: it.post.title }) %>
<h1><%= it.post.title %></h1>
<p>By <%= it.post.author %> on <%= new Date(it.post.createdAt).toLocaleDateString() %></p>
<% if (it.post.categories && it.post.categories.length > 0) { %>
<p>Categories:
<% it.post.categories.forEach((category, index) => { %>
<a href="/?category=<%= category %>"><%= category %></a><%= index < it.post.categories.length - 1 ? ', ' : '' %>
<% }) %>
</p>
<% } %>
<div><%= it.post.content %></div>
<div class="share-buttons">
<h3>Share this post:</h3>
<a href="https://twitter.com/intent/tweet?url=<%= encodeURIComponent(it.fullUrl) %>&text=<%= encodeURIComponent(it.post.title) %>" target="_blank" rel="noopener noreferrer">Share on Twitter</a>
<a href="https://www.facebook.com/sharer/sharer.php?u=<%= encodeURIComponent(it.fullUrl) %>" target="_blank" rel="noopener noreferrer">Share on Facebook</a>
<a href="https://www.linkedin.com/shareArticle?mini=true&url=<%= encodeURIComponent(it.fullUrl) %>&title=<%= encodeURIComponent(it.post.title) %>" target="_blank" rel="noopener noreferrer">Share on LinkedIn</a>
</div>
<!-- ... 评论部分保持不变 -->- 更新
src/routes/posts.ts文件,在获取单个文章的路由中添加完整的 URL:
.get("/posts/:id", async ({ params, request }) => {
const post = await db.select({
id: posts.id,
title: posts.title,
content: posts.content,
createdAt: posts.createdAt,
author: users.username,
categories: categories.name,
})
.from(posts)
.leftJoin(users, eq(posts.authorId, users.id))
.leftJoin(postCategories, eq(posts.id, postCategories.postId))
.leftJoin(categories, eq(postCategories.categoryId, categories.id))
.where(eq(posts.id, parseInt(params.id)))
.all();
if (post.length === 0) {
return null;
}
const categories = post.map(p => p.categories).filter(Boolean);
const fullUrl = `${request.headers.get('x-forwarded-proto') || 'http'}://${request.headers.get('host')}/posts/${params.id}`;
return { ...post[0], categories, fullUrl };
})- 接下来,让我们实现博客文章归档功能。首先,在
src/routes/posts.ts中添加一个新的路由来获取归档数据:
.get("/archive", async () => {
const archive = await db.select({
year: sql`strftime('%Y', ${posts.createdAt})`,
month: sql`strftime('%m', ${posts.createdAt})`,
count: sql`count(*)`,
})
.from(posts)
.groupBy(sql`strftime('%Y', ${posts.createdAt})`, sql`strftime('%m', ${posts.createdAt})`)
.orderBy(desc(sql`strftime('%Y', ${posts.createdAt})`), desc(sql`strftime('%m', ${posts.createdAt})`))
.all();
return archive;
})- 创建一个新的视图文件
src/views/archive.eta:
<% layout('./layouts/main.eta', { title: 'Archive' }) %>
<h1>Blog Archive</h1>
<% let currentYear = null; %>
<% it.archive.forEach(function(item) { %>
<% if (item.year !== currentYear) { %>
<% if (currentYear !== null) { %>
</ul>
<% } %>
<h2><%= item.year %></h2>
<ul>
<% currentYear = item.year; %>
<% } %>
<li>
<a href="/archive/<%= item.year %>/<%= item.month %>">
<%= new Date(item.year, item.month - 1).toLocaleString('default', { month: 'long' }) %>
(<%= item.count %> posts)
</a>
</li>
<% }) %>
<% if (currentYear !== null) { %>
</ul>
<% } %>- 在
src/index.ts中添加新的路由来显示归档页面:
app.get("/archive", async () => {
const archive = await postRoutes.handle({ method: 'GET', path: '/archive' });
return await renderFile(path.join(__dirname, "views", "archive.eta"), { archive });
});
app.get("/archive/:year/:month", async ({ params }) => {
const posts = await db.select({
id: posts.id,
title: posts.title,
createdAt: posts.createdAt,
author: users.username,
})
.from(posts)
.leftJoin(users, eq(posts.authorId, users.id))
.where(
and(
sql`strftime('%Y', ${posts.createdAt}) = ${params.year}`,
sql`strftime('%m', ${posts.createdAt}) = ${params.month}`
)
)
.orderBy(desc(posts.createdAt))
.all();
const monthName = new Date(parseInt(params.year), parseInt(params.month) - 1).toLocaleString('default', { month: 'long' });
return await renderFile(path.join(__dirname, "views", "archive-month.eta"), { posts, year: params.year, month: monthName });
});- 创建一个新的视图文件
src/views/archive-month.eta:
<% layout('./layouts/main.eta', { title: `Archive - ${it.month} ${it.year}` }) %>
<h1>Archive: <%= it.month %> <%= it.year %></h1>
<ul>
<% it.posts.forEach(function(post) { %>
<li>
<a href="/posts/<%= post.id %>"><%= post.title %></a>
<small>by <%= post.author %> on <%= new Date(post.createdAt).toLocaleDateString() %></small>
</li>
<% }) %>
</ul>
<p><a href="/archive">Back to full archive</a></p>- 更新
src/views/layouts/main.eta文件,在导航栏中添加归档链接:
<header>
<nav>
<a href="/">Home</a>
<a href="/posts/new">New Post</a>
<a href="/archive">Archive</a>
<% if (it.user) { %>
<a href="/settings">Settings</a>
<a href="/logout">Logout</a>
<% } else { %>
<a href="/login">Login</a>
<a href="/register">Register</a>
<% } %>
<a href="/rss.xml">RSS Feed</a>
</nav>
</header>- 最后,更新
public/styles/main.css文件,添加一些样式:
/* ... 前面的样式保持不变 */
.share-buttons {
margin-top: 2rem;
}
.share-buttons a {
display: inline-block;
margin-right: 1rem;
padding: 0.5rem 1rem;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 4px;
}
.share-buttons a:hover {
background-color: #0056b3;
}
.archive-list {
list-style-type: none;
padding: 0;
}
.archive-list li {
margin-bottom: 0.5rem;
}
.archive-list small {
color: #666;
margin-left: 0.5rem;
}这些更改实现了社交媒体分享功能和博客文章归档功能:
- 在每篇文章的详情页面添加了社交媒体分享按钮,允许用户轻松分享文章到 Twitter、Facebook 和 LinkedIn。
- 创建了一个归档页面,按年和月份组织所有的博客文章。
- 为每个月份创建了一个单独的页面,显示该月份的所有文章。
- 在导航栏中添加了归档链接,使用户可以轻松访问归档页面。
- 更新了样式以美化分享按钮和归档页面的显示。
这些功能提高了博客的可分享性和可导航性,使用户更容易找到和分享过去的文章。
接下来,我们可以考虑添加以下功能:
- 文章搜索功能
- 用户头像上传
- 评论系统的改进(如回复功能、评论分页等)
- 文章编辑器的改进(如支持 Markdown 或富文本编辑)
你希望继续哪个方向,或者有其他想法吗?