好的,让我们来实现文章搜索功能。我们将创建一个简单的搜索页面,允许用户通过标题、内容或作者名称搜索文章。
第十六部分:实现文章搜索功能
- 首先,在
src/routes目录下创建一个新文件search.ts:
import { Elysia } from "elysia";
import { db } from "../db";
import { posts, users, categories, postCategories } from "../db/schema";
import { eq, like, or, and } from "drizzle-orm";
export const searchRoutes = new Elysia()
.get("/search", async ({ query }) => {
const { q } = query;
if (!q) {
return { posts: [], query: "" };
}
const searchResults = 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(
or(
like(posts.title, `%${q}%`),
like(posts.content, `%${q}%`),
like(users.username, `%${q}%`)
)
)
.all();
// 对结果进行处理,合并相同文章的类别
const processedResults = searchResults.reduce((acc, curr) => {
const existingPost = acc.find(post => post.id === curr.id);
if (existingPost) {
if (curr.categories && !existingPost.categories.includes(curr.categories)) {
existingPost.categories.push(curr.categories);
}
} else {
acc.push({
...curr,
categories: curr.categories ? [curr.categories] : []
});
}
return acc;
}, []);
return { posts: processedResults, query: q };
});- 在
src/index.ts中导入并使用新的搜索路由:
import { searchRoutes } from "./routes/search";
// ... 其他导入保持不变
app.use(searchRoutes);
// ... 其他代码保持不变- 创建一个新的视图文件
src/views/search.eta:
<% layout('./layouts/main.eta', { title: 'Search Results' }) %>
<h1>Search Results</h1>
<form action="/search" method="GET">
<input type="text" name="q" value="<%= it.query %>" placeholder="Search for posts...">
<button type="submit">Search</button>
</form>
<% if (it.posts.length > 0) { %>
<ul>
<% it.posts.forEach(post => { %>
<li>
<h2><a href="/posts/<%= post.id %>"><%= post.title %></a></h2>
<p>By <%= post.author %> on <%= new Date(post.createdAt).toLocaleDateString() %></p>
<% if (post.categories && post.categories.length > 0) { %>
<p>Categories:
<%= post.categories.join(', ') %>
</p>
<% } %>
<p><%= post.content.substring(0, 200) %>...</p>
</li>
<% }) %>
</ul>
<% } else if (it.query) { %>
<p>No results found for "<%= it.query %>"</p>
<% } %>- 更新
src/routes/search.ts文件,添加渲染搜索结果页面的逻辑:
import { Elysia } from "elysia";
import { db } from "../db";
import { posts, users, categories, postCategories } from "../db/schema";
import { eq, like, or, and } from "drizzle-orm";
export const searchRoutes = new Elysia()
.get("/search", async ({ query, render }) => {
const { q } = query;
if (!q) {
return render("search", { posts: [], query: "" });
}
// ... 保持搜索逻辑不变
return render("search", { posts: processedResults, query: q });
});- 在主布局文件
src/views/layouts/main.eta中添加搜索表单:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= it.title %> - My Blog</title>
<link rel="stylesheet" href="/styles/main.css">
</head>
<body>
<header>
<nav>
<a href="/">Home</a>
<a href="/posts/new">New Post</a>
<% if (it.user) { %>
<a href="/logout">Logout</a>
<% } else { %>
<a href="/login">Login</a>
<a href="/register">Register</a>
<% } %>
<form action="/search" method="GET" class="search-form">
<input type="text" name="q" placeholder="Search...">
<button type="submit">Search</button>
</form>
</nav>
</header>
<main>
<%~ it.body %>
</main>
<footer>
<p>© 2023 My Blog</p>
</footer>
</body>
</html>- 更新
public/styles/main.css文件,添加一些搜索相关的样式:
/* ... 前面的样式保持不变 */
.search-form {
display: inline-block;
margin-left: 20px;
}
.search-form input[type="text"] {
padding: 5px;
width: 200px;
}
.search-form button {
padding: 5px 10px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
.search-results li {
margin-bottom: 20px;
border-bottom: 1px solid #ddd;
padding-bottom: 10px;
}
.search-results h2 {
margin-bottom: 5px;
}
.search-results p {
margin: 5px 0;
}这些更改实现了文章搜索功能:
- 创建了一个新的搜索路由,处理搜索请求。
- 实现了基于标题、内容和作者名称的搜索逻辑。
- 创建了一个新的搜索结果页面,显示搜索结果。
- 在主布局中添加了一个搜索表单,使搜索功能在所有页面都可用。
- 添加了相应的样式,使搜索功能看起来更加美观。
主要改进包括:
- 用户可以通过标题、内容或作者名称搜索文章。
- 搜索结果页面显示匹配的文章,包括标题、作者、发布日期、类别和内容预览。
- 搜索表单在所有页面的顶部都可用,提高了可访问性。
这个搜索功能为用户提供了一种快速找到感兴趣内容的方法,提高了博客的可用性。
接下来,我们可以考虑添加以下功能:
- 用户头像上传
- 文章预览功能
- 标签云或热门标签功能
- 高级搜索选项(如按日期范围或特定类别搜索)
你希望继续哪个方向,或者有其他想法吗?