好的,让我们来实现文章预览功能。这个功能将允许用户在发布文章之前预览其外观。我们将创建一个预览页面,并在编辑器中添加一个预览按钮。

第十七部分:实现文章预览功能

  1. 首先,更新 src/routes/posts.ts 文件,添加预览路由:
import { Elysia } from "elysia";
import { db } from "../db";
import { posts, users, categories, postCategories } from "../db/schema";
import { eq } from "drizzle-orm";
import { marked } from 'marked'; // 请确保已安装 marked 包:bun add marked
 
export const postRoutes = new Elysia()
  // ... 保持其他路由不变
 
  .post("/posts/preview", async ({ body, render }) => {
    const { title, content, categoryIds } = body;
 
    // 获取分类名称
    const categoriesData = await db
      .select({ id: categories.id, name: categories.name })
      .from(categories)
      .where(eq(categories.id, categoryIds))
      .all();
 
    const previewPost = {
      title,
      content: marked(content), // 将 Markdown 转换为 HTML
      createdAt: new Date(),
      author: "Preview Author",
      categories: categoriesData.map(cat => cat.name),
    };
 
    return render("posts/preview", { post: previewPost });
  });
  1. 创建一个新的视图文件 src/views/posts/preview.eta
<% layout('../layouts/main.eta', { title: 'Preview Post' }) %>
 
<h1>Preview: <%= it.post.title %></h1>
 
<div class="post-meta">
  <p>By <%= it.post.author %> on <%= it.post.createdAt.toLocaleDateString() %></p>
  <p>Categories: <%= it.post.categories.join(', ') %></p>
</div>
 
<div class="post-content">
  <%~ it.post.content %>
</div>
 
<a href="#" onclick="window.history.back(); return false;">Back to Editor</a>
  1. 更新 src/views/posts/new.etasrc/views/posts/edit.eta 文件,添加预览按钮和必要的 JavaScript:
<% layout('../layouts/main.eta', { title: it.post ? 'Edit Post' : 'New Post' }) %>
 
<h1><%= it.post ? 'Edit Post' : 'New Post' %></h1>
 
<form id="postForm" action="<%= it.post ? `/posts/${it.post.id}` : '/posts' %>" method="POST">
  <div>
    <label for="title">Title:</label>
    <input type="text" id="title" name="title" value="<%= it.post ? it.post.title : '' %>" required>
  </div>
  <div>
    <label for="content">Content:</label>
    <textarea id="content" name="content" required><%= it.post ? it.post.content : '' %></textarea>
  </div>
  <div>
    <label>Categories:</label>
    <% it.categories.forEach(category => { %>
      <label>
        <input type="checkbox" name="categoryIds" value="<%= category.id %>"
          <%= it.post && it.post.categories.includes(category.name) ? 'checked' : '' %>>
        <%= category.name %>
      </label>
    <% }) %>
  </div>
  <button type="submit"><%= it.post ? 'Update' : 'Create' %> Post</button>
  <button type="button" id="previewButton">Preview</button>
</form>
 
<script>
document.getElementById('previewButton').addEventListener('click', async (e) => {
  e.preventDefault();
  const form = document.getElementById('postForm');
  const formData = new FormData(form);
 
  const response = await fetch('/posts/preview', {
    method: 'POST',
    body: formData
  });
 
  if (response.ok) {
    const previewWindow = window.open('', 'Preview', 'width=800,height=600');
    previewWindow.document.write(await response.text());
    previewWindow.document.close();
  } else {
    alert('Error generating preview');
  }
});
</script>
  1. src/index.ts 中添加新的预览路由:
import { postRoutes } from "./routes/posts";
 
// ... 其他代码保持不变
 
app.post("/posts/preview", async (context) => {
  return await postRoutes.handle(context);
});
  1. 更新 public/styles/main.css 文件,添加一些预览相关的样式:
/* ... 前面的样式保持不变 */
 
.post-meta {
  font-style: italic;
  color: #666;
  margin-bottom: 20px;
}
 
.post-content {
  line-height: 1.6;
}
 
.post-content h1, .post-content h2, .post-content h3 {
  margin-top: 20px;
  margin-bottom: 10px;
}
 
.post-content p {
  margin-bottom: 15px;
}
 
.post-content img {
  max-width: 100%;
  height: auto;
}
 
#previewButton {
  margin-left: 10px;
  background-color: #28a745;
}
  1. 安装 marked 包来处理 Markdown:
bun add marked

这些更改实现了文章预览功能:

  1. 创建了一个新的预览路由,处理预览请求。
  2. 实现了将 Markdown 内容转换为 HTML 的逻辑。
  3. 创建了一个新的预览页面,显示文章的预览版本。
  4. 在文章编辑器中添加了一个预览按钮。
  5. 添加了相应的样式,使预览功能看起来更加美观。

主要改进包括:

  • 用户可以在发布或更新文章之前预览其外观。
  • 预览功能支持 Markdown 格式,允许用户看到格式化后的内容。
  • 预览在新窗口中打开,方便用户比较和编辑。

这个预览功能为用户提供了一种在发布之前检查文章外观的方法,有助于提高内容质量和用户体验。

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

  1. 用户头像上传
  2. 标签云或热门标签功能
  3. 高级搜索选项(如按日期范围或特定类别搜索)
  4. 文章归档功能

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