feat:增加博客统计接口

This commit is contained in:
2025-10-27 15:04:47 +08:00
parent 02983a882d
commit 8ad63f9a78
7 changed files with 265 additions and 16 deletions

View File

@@ -13,6 +13,7 @@ from schemas.pagination import PageResult
from schemas.paginate_query import paginate_query
from middleware.exceptions import AppException
from service.blog_elastic_service import add_blog_elastic
from service.blog_stats_service import query_blog_overview
from utils.blog_utils import get_blog_summary, get_word_count, get_read_duration
@@ -78,7 +79,31 @@ def query_blog_by_condition(db: Session, blog_query: BlogQuery) -> List[BlogResp
results = db.execute(stmt).fetchall()
return [BlogResponse.from_orm(result) for result in results]
return [BlogResponse.model_validate(result) for result in results]
def query_unapproved_blog(db: Session) -> List[BlogResponse]:
stmt = ((select(
Blog.id,
Blog.title,
Blog.top_value.label("topValue"),
Blog.is_great.label("isGreat"),
BlogCategory.name.label("category"),
Blog.summary,
BlogContent.content.label("content"),
Blog.word_count.label("wordCount"),
Blog.read_duration.label("readDuration"),
Blog.is_approved.label("isApproved"),
Blog.create_time.label("createTime"),
Blog.update_time.label("updateTime")
).where(Blog.is_approved == 0)
.outerjoin(BlogCategory, Blog.category_id == BlogCategory.id)
.outerjoin(BlogContent, Blog.content_id == BlogContent.id))
.order_by(desc(Blog.update_time)))
results = db.execute(stmt).fetchall()
return [BlogResponse.model_validate(result) for result in results]
def query_blog_by_id(db: Session, blog_id: int) -> BlogResponse:
@@ -231,23 +256,16 @@ def query_blog_category(db: Session) -> List[BlogCategoryResponse]:
results = db.execute(query).fetchall()
return [BlogCategoryResponse.from_orm(result) for result in results]
return [BlogCategoryResponse.model_validate(result) for result in results]
def query_blog_stats(db: Session) -> BlogStatsResponse:
blog_count_stmt = select(func.count(Blog.id)).where(Blog.is_approved == 1)
blog_count = db.execute(blog_count_stmt).scalar() or 0
word_count_stmt = select(func.sum(Blog.word_count)).where(Blog.is_approved == 1)
word_count = db.execute(word_count_stmt).scalar() or 0
category_count_stmt = select(func.count(distinct(Blog.category_id))).where(Blog.is_approved == 1)
category_count = db.execute(category_count_stmt).scalar() or 0
blog_stats = query_blog_overview(db)
return BlogStatsResponse(
blogCount=blog_count,
categoryCount=category_count,
wordCount=word_count
blogCount=blog_stats.blogCount,
categoryCount=blog_stats.categoryCount,
wordCount=blog_stats.wordCount
)
@@ -255,7 +273,7 @@ def query_blog_latest(db: Session) -> List[BlogLatestResponse]:
stmt = select(Blog.id, Blog.title).where(Blog.is_approved == 1).order_by(desc(Blog.update_time)).limit(5)
results = db.execute(stmt).fetchall()
return [BlogLatestResponse.from_orm(result) for result in results]
return [BlogLatestResponse.model_validate(result) for result in results]
def query_blog_adjacent(db: Session, blog_id: int) -> List[BlogAdjacentResponse]:
@@ -319,7 +337,7 @@ def query_blog_comment(db: Session, blog_id: int) -> List[BlogCommentResponse]:
).where(BlogComment.blog_id == blog_id, BlogComment.is_approved == 1).order_by(desc(BlogComment.create_time))
results = db.execute(stmt).fetchall()
return [BlogCommentResponse.from_orm(result) for result in results]
return [BlogCommentResponse.model_validate(result) for result in results]
def add_blog_comment(db: Session, request: Request, blog_id: int, blog_comment: BlogCommentCreate) -> bool:

View File

@@ -0,0 +1,143 @@
from datetime import datetime
from typing import List
from sqlalchemy import select, func, distinct, extract
from sqlalchemy.orm import Session
from models.blog import Blog, BlogVisit, BlogComment, BlogCategory
from schemas.blog_stats import BlogOverview, BlogChartStats
def query_blog_overview(db: Session) -> BlogOverview:
blog_count_stmt = select(func.count(Blog.id)).where(Blog.is_approved == 1)
blog_count = db.execute(blog_count_stmt).scalar() or 0
word_count_stmt = select(func.sum(Blog.word_count)).where(Blog.is_approved == 1)
word_count = db.execute(word_count_stmt).scalar() or 0
category_count_stmt = select(func.count(distinct(Blog.category_id))).where(Blog.is_approved == 1)
category_count = db.execute(category_count_stmt).scalar() or 0
great_count_stmt = select(func.count(Blog.id)).where(Blog.is_approved == 1, Blog.is_great == 1)
great_count = db.execute(great_count_stmt).scalar() or 0
visit_count_stmt = select(func.count(BlogVisit.id))
visit_count = db.execute(visit_count_stmt).scalar() or 0
return BlogOverview(
blogCount=blog_count,
categoryCount=category_count,
wordCount=word_count,
greatCount=great_count,
visitCount=visit_count
)
def query_blog_category(db: Session) -> List[BlogChartStats]:
query = (
select(
BlogCategory.name.label("name"),
func.count(Blog.id).label("value")
)
.where(Blog.is_approved == 1)
.outerjoin(BlogCategory, Blog.category_id == BlogCategory.id)
.group_by(BlogCategory.name))
results = db.execute(query).fetchall()
return [BlogChartStats.model_validate(result) for result in results]
def query_blog_approved_monthly(db: Session, year: int = None) -> List[BlogChartStats]:
current_year = datetime.now().year
target_year = year if year else current_year
# extract():返回日期/时间的单独部分
stmt = (
select(
func.concat(extract('month', Blog.create_time), '').label('name'),
func.count(Blog.id).label('value')
)
.where(
Blog.is_approved == 1,
extract('year', Blog.create_time) == target_year
)
.group_by('name')
)
results = db.execute(stmt).fetchall()
return [BlogChartStats.model_validate(result) for result in results]
def query_blog_visit_monthly(db: Session, year: int = None) -> List[BlogChartStats]:
current_year = datetime.now().year
target_year = year if year else current_year
stmt = (
select(
func.concat(extract('month', BlogVisit.create_time), '').label('name'),
func.count(BlogVisit.id).label('value')
)
.where(
extract('year', BlogVisit.create_time) == target_year
)
.group_by('name')
)
results = db.execute(stmt).fetchall()
return [BlogChartStats.model_validate(result) for result in results]
def query_blog_visit_rank(db: Session, limit: int = 5) -> List[BlogChartStats]:
stmt = (
select(
Blog.title.label('name'),
func.count(BlogVisit.id).label('value')
)
.join(BlogVisit, Blog.id == BlogVisit.blog_id)
.where(Blog.is_approved == 1)
.group_by(Blog.title)
.order_by(func.count(BlogVisit.id).desc())
.limit(limit)
)
results = db.execute(stmt).fetchall()
return [BlogChartStats.model_validate(result) for result in results]
def query_blog_read_rank(db: Session, limit: int = 5) -> List[BlogChartStats]:
stmt = (
select(
Blog.title.label('name'),
func.round(func.sum(Blog.read_duration)).label('value')
)
.where(Blog.is_approved == 1)
.group_by(Blog.title)
.order_by(func.sum(Blog.read_duration).desc())
.limit(limit)
)
results = db.execute(stmt).fetchall()
return [BlogChartStats.model_validate(result) for result in results]
def query_blog_comment_rank(db: Session, limit: int = 5) -> List[BlogChartStats]:
stmt = (
select(
Blog.title.label('name'),
func.count(BlogComment.id).label('value')
)
.join(BlogComment, Blog.id == BlogComment.blog_id)
.where(Blog.is_approved == 1)
.group_by(Blog.title)
.order_by(func.count(BlogComment.id).desc())
.limit(limit)
)
results = db.execute(stmt).fetchall()
return [BlogChartStats.model_validate(result) for result in results]