perf: aggregate homepage data and trim frontend loading

This commit is contained in:
2026-03-31 00:25:58 +08:00
parent 99b308e800
commit a9a05aa105
4 changed files with 137 additions and 18 deletions

View File

@@ -10,8 +10,10 @@ use uuid::Uuid;
use crate::{
controllers::admin::check_auth,
models::_entities::site_settings::{self, ActiveModel, Entity, Model},
services::ai,
models::_entities::{
categories, friend_links, posts, site_settings::{self, ActiveModel, Entity, Model}, tags,
},
services::{ai, content},
};
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
@@ -154,6 +156,23 @@ pub struct PublicSiteSettingsResponse {
pub paragraph_comments_enabled: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct HomeCategorySummary {
pub id: i32,
pub name: String,
pub slug: String,
pub count: usize,
}
#[derive(Clone, Debug, Serialize)]
pub struct HomePageResponse {
pub site_settings: PublicSiteSettingsResponse,
pub posts: Vec<posts::Model>,
pub tags: Vec<tags::Model>,
pub friend_links: Vec<friend_links::Model>,
pub categories: Vec<HomeCategorySummary>,
}
fn normalize_optional_string(value: Option<String>) -> Option<String> {
value.and_then(|item| {
let trimmed = item.trim().to_string();
@@ -664,6 +683,55 @@ fn public_response(model: Model) -> PublicSiteSettingsResponse {
}
}
#[debug_handler]
pub async fn home(State(ctx): State<AppContext>) -> Result<Response> {
content::sync_markdown_posts(&ctx).await?;
let site_settings = public_response(load_current(&ctx).await?);
let posts = posts::Entity::find()
.order_by_desc(posts::Column::CreatedAt)
.all(&ctx.db)
.await?;
let tags = tags::Entity::find().all(&ctx.db).await?;
let friend_links = friend_links::Entity::find()
.order_by_desc(friend_links::Column::CreatedAt)
.all(&ctx.db)
.await?;
let category_items = categories::Entity::find()
.order_by_asc(categories::Column::Slug)
.all(&ctx.db)
.await?;
let categories = category_items
.into_iter()
.map(|category| {
let name = category
.name
.clone()
.unwrap_or_else(|| category.slug.clone());
let count = posts
.iter()
.filter(|post| post.category.as_deref().map(str::trim) == Some(name.as_str()))
.count();
HomeCategorySummary {
id: category.id,
name,
slug: category.slug,
count,
}
})
.collect::<Vec<_>>();
format::json(HomePageResponse {
site_settings,
posts,
tags,
friend_links,
categories,
})
}
#[debug_handler]
pub async fn show(State(ctx): State<AppContext>) -> Result<Response> {
format::json(public_response(load_current(&ctx).await?))
@@ -687,6 +755,7 @@ pub async fn update(
pub fn routes() -> Routes {
Routes::new()
.prefix("api/site_settings/")
.add("home", get(home))
.add("/", get(show))
.add("/", put(update))
.add("/", patch(update))