好的,让我们来实现文章预览功能。这个功能将允许用户在发布文章之前预览其外观。我们将创建一个预览页面,并在编辑器中添加一个预览按钮。
第十七部分:实现文章预览功能
- 首先,更新
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 });
});- 创建一个新的视图文件
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>- 更新
src/views/posts/new.eta和src/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>- 在
src/index.ts中添加新的预览路由:
import { postRoutes } from "./routes/posts";
// ... 其他代码保持不变
app.post("/posts/preview", async (context) => {
return await postRoutes.handle(context);
});- 更新
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;
}- 安装
marked包来处理 Markdown:
bun add marked这些更改实现了文章预览功能:
- 创建了一个新的预览路由,处理预览请求。
- 实现了将 Markdown 内容转换为 HTML 的逻辑。
- 创建了一个新的预览页面,显示文章的预览版本。
- 在文章编辑器中添加了一个预览按钮。
- 添加了相应的样式,使预览功能看起来更加美观。
主要改进包括:
- 用户可以在发布或更新文章之前预览其外观。
- 预览功能支持 Markdown 格式,允许用户看到格式化后的内容。
- 预览在新窗口中打开,方便用户比较和编辑。
这个预览功能为用户提供了一种在发布之前检查文章外观的方法,有助于提高内容质量和用户体验。
接下来,我们可以考虑添加以下功能:
- 用户头像上传
- 标签云或热门标签功能
- 高级搜索选项(如按日期范围或特定类别搜索)
- 文章归档功能
你希望继续哪个方向,或者有其他想法吗?