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.
295 lines
9.4 KiB
295 lines
9.4 KiB
import ArticleModel from "db/models/ArticleModel.js"
|
|
import CommonError from "utils/error/CommonError.js"
|
|
|
|
class ArticleService {
|
|
// 获取所有文章
|
|
async getAllArticles() {
|
|
try {
|
|
return await ArticleModel.findAll()
|
|
} catch (error) {
|
|
throw new CommonError(`获取文章列表失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取已发布的文章
|
|
async getPublishedArticles() {
|
|
try {
|
|
return await ArticleModel.findPublished()
|
|
} catch (error) {
|
|
throw new CommonError(`获取已发布文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取草稿文章
|
|
async getDraftArticles() {
|
|
try {
|
|
return await ArticleModel.findDrafts()
|
|
} catch (error) {
|
|
throw new CommonError(`获取草稿文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 根据ID获取文章
|
|
async getArticleById(id) {
|
|
try {
|
|
const article = await ArticleModel.findById(id)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
return article
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`获取文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 根据slug获取文章
|
|
async getArticleBySlug(slug) {
|
|
try {
|
|
const article = await ArticleModel.findBySlug(slug)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
return article
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`获取文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 根据作者获取文章
|
|
async getArticlesByAuthor(author) {
|
|
try {
|
|
return await ArticleModel.findByAuthor(author)
|
|
} catch (error) {
|
|
throw new CommonError(`获取作者文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 根据分类获取文章
|
|
async getArticlesByCategory(category) {
|
|
try {
|
|
return await ArticleModel.findByCategory(category)
|
|
} catch (error) {
|
|
throw new CommonError(`获取分类文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 根据标签获取文章
|
|
async getArticlesByTags(tags) {
|
|
try {
|
|
return await ArticleModel.findByTags(tags)
|
|
} catch (error) {
|
|
throw new CommonError(`获取标签文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 关键词搜索文章
|
|
async searchArticles(keyword) {
|
|
try {
|
|
if (!keyword || keyword.trim() === '') {
|
|
throw new CommonError("搜索关键词不能为空")
|
|
}
|
|
return await ArticleModel.searchByKeyword(keyword.trim())
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`搜索文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 创建文章
|
|
async createArticle(data) {
|
|
try {
|
|
if (!data.title || !data.content) {
|
|
throw new CommonError("标题和内容为必填字段")
|
|
}
|
|
return await ArticleModel.create(data)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`创建文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 更新文章
|
|
async updateArticle(id, data) {
|
|
try {
|
|
const article = await ArticleModel.findById(id)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
return await ArticleModel.update(id, data)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`更新文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 删除文章
|
|
async deleteArticle(id) {
|
|
try {
|
|
const article = await ArticleModel.findById(id)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
return await ArticleModel.delete(id)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`删除文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 发布文章
|
|
async publishArticle(id) {
|
|
try {
|
|
const article = await ArticleModel.findById(id)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
if (article.status === 'published') {
|
|
throw new CommonError("文章已经是发布状态")
|
|
}
|
|
return await ArticleModel.publish(id)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`发布文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 取消发布文章
|
|
async unpublishArticle(id) {
|
|
try {
|
|
const article = await ArticleModel.findById(id)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
if (article.status === 'draft') {
|
|
throw new CommonError("文章已经是草稿状态")
|
|
}
|
|
return await ArticleModel.unpublish(id)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`取消发布文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 增加文章阅读量
|
|
async incrementViewCount(id) {
|
|
try {
|
|
const article = await ArticleModel.findById(id)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
return await ArticleModel.incrementViewCount(id)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`增加阅读量失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 根据日期范围获取文章
|
|
async getArticlesByDateRange(startDate, endDate) {
|
|
try {
|
|
if (!startDate || !endDate) {
|
|
throw new CommonError("开始日期和结束日期不能为空")
|
|
}
|
|
return await ArticleModel.findByDateRange(startDate, endDate)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`获取日期范围文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取文章统计信息
|
|
async getArticleStats() {
|
|
try {
|
|
const [totalCount, publishedCount, categoryStats, statusStats] = await Promise.all([
|
|
ArticleModel.getArticleCount(),
|
|
ArticleModel.getPublishedArticleCount(),
|
|
ArticleModel.getArticleCountByCategory(),
|
|
ArticleModel.getArticleCountByStatus()
|
|
])
|
|
|
|
return {
|
|
total: totalCount,
|
|
published: publishedCount,
|
|
draft: totalCount - publishedCount,
|
|
byCategory: categoryStats,
|
|
byStatus: statusStats
|
|
}
|
|
} catch (error) {
|
|
throw new CommonError(`获取文章统计失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取最近文章
|
|
async getRecentArticles(limit = 10) {
|
|
try {
|
|
return await ArticleModel.getRecentArticles(limit)
|
|
} catch (error) {
|
|
throw new CommonError(`获取最近文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取热门文章
|
|
async getPopularArticles(limit = 10) {
|
|
try {
|
|
return await ArticleModel.getPopularArticles(limit)
|
|
} catch (error) {
|
|
throw new CommonError(`获取热门文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取精选文章
|
|
async getFeaturedArticles(limit = 5) {
|
|
try {
|
|
return await ArticleModel.getFeaturedArticles(limit)
|
|
} catch (error) {
|
|
throw new CommonError(`获取精选文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 获取相关文章
|
|
async getRelatedArticles(articleId, limit = 5) {
|
|
try {
|
|
const article = await ArticleModel.findById(articleId)
|
|
if (!article) {
|
|
throw new CommonError("文章不存在")
|
|
}
|
|
return await ArticleModel.getRelatedArticles(articleId, limit)
|
|
} catch (error) {
|
|
if (error instanceof CommonError) throw error
|
|
throw new CommonError(`获取相关文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
// 分页获取文章
|
|
async getArticlesWithPagination(page = 1, pageSize = 10, status = 'published') {
|
|
try {
|
|
let query = ArticleModel.findPublished()
|
|
if (status === 'all') {
|
|
query = ArticleModel.findAll()
|
|
} else if (status === 'draft') {
|
|
query = ArticleModel.findDrafts()
|
|
}
|
|
|
|
const offset = (page - 1) * pageSize
|
|
const articles = await query.limit(pageSize).offset(offset)
|
|
const total = await ArticleModel.getPublishedArticleCount()
|
|
|
|
return {
|
|
articles,
|
|
pagination: {
|
|
current: page,
|
|
pageSize,
|
|
total,
|
|
totalPages: Math.ceil(total / pageSize)
|
|
}
|
|
}
|
|
} catch (error) {
|
|
throw new CommonError(`分页获取文章失败: ${error.message}`)
|
|
}
|
|
}
|
|
}
|
|
|
|
export default ArticleService
|
|
export { ArticleService }
|
|
|