import { ArticleModel } from "../../db/models/ArticleModel.js" import Router from "utils/router.js" import { marked } from "marked" class ArticleController { async index(ctx) { const { page = 1, view = 'grid' } = ctx.query const limit = 12 // 每页显示的文章数量 const offset = (page - 1) * limit // 获取文章总数 const total = await ArticleModel.getPublishedArticleCount() const totalPages = Math.ceil(total / limit) // 获取分页文章 const articles = await ArticleModel.findPublished(offset, limit) // 获取所有分类和标签 const categories = await ArticleModel.getArticleCountByCategory() const allArticles = await ArticleModel.findPublished() const tags = new Set() allArticles.forEach(article => { if (article.tags) { article.tags.split(',').forEach(tag => { tags.add(tag.trim()) }) } }) return ctx.render("page/articles/index", { articles, categories: categories.map(c => c.category), tags: Array.from(tags), currentPage: parseInt(page), totalPages, view, title: "文章列表", }, { includeUser: true, includeSite: true, }) } async show(ctx) { const { slug } = ctx.params console.log(slug); const article = await ArticleModel.findBySlug(slug) if (!article) { ctx.throw(404, "文章不存在") } // 增加阅读次数 await ArticleModel.incrementViewCount(article.id) // 将文章内容解析为HTML article.content = marked(article.content || '') // 获取相关文章 const relatedArticles = await ArticleModel.getRelatedArticles(article.id) return ctx.render("page/articles/article", { article, relatedArticles, title: article.title, }, { includeUser: true, }) } async byCategory(ctx) { const { category } = ctx.params const articles = await ArticleModel.findByCategory(category) return ctx.render("page/articles/category", { articles, category, title: `${category} - 分类文章`, }, { includeUser: true, }) } async byTag(ctx) { const { tag } = ctx.params const articles = await ArticleModel.findByTags(tag) return ctx.render("page/articles/tag", { articles, tag, title: `${tag} - 标签文章`, }, { includeUser: true, }) } async search(ctx) { const { q } = ctx.query if(!q) { return ctx.set('hx-redirect', '/articles') } const articles = await ArticleModel.searchByKeyword(q) return ctx.render("page/articles/search", { articles, keyword: q, title: `搜索:${q}`, }, { includeUser: true, }) } static createRoutes() { const controller = new ArticleController() const router = new Router({ auth: true, prefix: "/articles" }) router.get("", controller.index, { auth: false }) // 允许未登录访问 router.get("/", controller.index, { auth: false }) // 允许未登录访问 router.get("/search", controller.search, { auth: false }) router.get("/category/:category", controller.byCategory) router.get("/tag/:tag", controller.byTag) router.get("/:slug", controller.show) return router } } export default ArticleController export { ArticleController }