You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.7 KiB
130 lines
3.7 KiB
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 }
|
|
|