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

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 }