好的,让我们来实现社交媒体分享功能和博客文章归档功能。

第十三部分:实现社交媒体分享功能和博客文章归档

  1. 首先,让我们添加社交媒体分享功能。我们将使用简单的分享链接,而不是复杂的第三方插件。

更新 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>
 
<!-- ... 评论部分保持不变 -->
  1. 更新 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 };
})
  1. 接下来,让我们实现博客文章归档功能。首先,在 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;
})
  1. 创建一个新的视图文件 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>
<% } %>
  1. 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 });
});
  1. 创建一个新的视图文件 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>
  1. 更新 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>
  1. 最后,更新 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;
}

这些更改实现了社交媒体分享功能和博客文章归档功能:

  1. 在每篇文章的详情页面添加了社交媒体分享按钮,允许用户轻松分享文章到 Twitter、Facebook 和 LinkedIn。
  2. 创建了一个归档页面,按年和月份组织所有的博客文章。
  3. 为每个月份创建了一个单独的页面,显示该月份的所有文章。
  4. 在导航栏中添加了归档链接,使用户可以轻松访问归档页面。
  5. 更新了样式以美化分享按钮和归档页面的显示。

这些功能提高了博客的可分享性和可导航性,使用户更容易找到和分享过去的文章。

接下来,我们可以考虑添加以下功能:

  1. 文章搜索功能
  2. 用户头像上传
  3. 评论系统的改进(如回复功能、评论分页等)
  4. 文章编辑器的改进(如支持 Markdown 或富文本编辑)

你希望继续哪个方向,或者有其他想法吗?