use sea_orm::{ColumnTrait, Condition, DatabaseConnection, EntityTrait, NotSet, PaginatorTrait}; use sea_orm::{ActiveModelTrait, QueryFilter, QueryOrder, QuerySelect}; use sea_orm::ActiveValue::Set; use crate::{APPLICATION_CONTEXT, view}; use crate::common::err::{AppError, log_error}; use crate::common::Result; use crate::entity::{article, category, tag}; use crate::form::ArticleForm; use crate::param::ArticleParams; pub struct ArticleService; impl ArticleService { pub async fn index(handler_name: &str, params: ArticleParams) -> Result { let conn = APPLICATION_CONTEXT.get::(); let condition = Condition::all() .add(article::Column::IsDel.eq(false)) .add_option( params.keyword_opt().map(|n| article::Column::Title.contains(&n)) ) .add_option(params.is_del_opt().map(|n| article::Column::IsDel.eq(n))); let mut select = article::Entity::find() .filter(condition); let page = params.page(); // 当前页码 let page_size = params.page_size(); // 每页条数,默认15 if let Some(ord) = params.order() { select = select.order_by(category::Column::Id, ord); } let paginator = select .find_also_related(category::Entity) .paginate(conn, page_size); let page_total = paginator.num_pages().await.map_err(AppError::from)?; let list: Vec<(article::Model, Option)> = paginator .fetch_page(page) .await .map_err(AppError::from) .map_err(log_error(handler_name))?; Ok(view::ArticlesTemplate { list, page_total, params, }) } pub async fn add_ui(handler_name: &str) -> Result { let conn = APPLICATION_CONTEXT.get::(); let categies = category::Entity::find() .filter(category::Column::IsDel.eq(false)) .limit(100) .order_by_asc(category::Column::Id) .all(conn) .await .map_err(AppError::from) .map_err(log_error(handler_name))?; Ok(view::ArticleAddTemplate { categies }) } pub async fn add(handler_name: &str, frm: ArticleForm) -> Result { let conn = APPLICATION_CONTEXT.get::(); article::ActiveModel { id: NotSet, title: Set(frm.title), category_id: Set(frm.category_id), content: Set(frm.content), ..Default::default() }.save(conn) .await .map_err(AppError::from) .map_err(log_error(handler_name)) } pub async fn list_with_tags(handler_name: &str) -> Result { let conn = APPLICATION_CONTEXT.get::(); let list = article::Entity::find() .find_with_related(tag::Entity) .all(conn) .await .map_err(AppError::from) .map_err(log_error(handler_name))?; let mut ss = vec![]; for item in list { let (article, tags) = item; let tags = tags .iter() .map(|tag| format!("【#{} - {}】", &tag.id, &tag.name)) .collect::>() .join(",") .to_string(); let s = format!( "文章ID: {}, 文章标题: {}, 标签: {}", &article.id, &article.title, tags, ); ss.push(s); } Ok(ss.join("\n").to_string()) } }