tdm_server_rust/service/
author_service.rs1use crate::{
6 app::AppState,
7 cache::on_author_or_magazine_renamed,
8 common::PageBean,
9 entity::{author::Author, manga::MangaListVo},
10 error::{ApiResult, AppError},
11 repository::{author_repo::AuthorRepository, manga_repo::MangaRepository},
12 utils::page::{paginate, slice_rows},
13};
14
15pub struct AuthorService;
17
18impl AuthorService {
19 #[tracing::instrument(skip_all, level = "debug")]
21 pub async fn get_authors(
22 state: &AppState,
23 page: i32,
24 page_size: i32,
25 author_id: Option<i16>,
26 author_name: Option<String>,
27 ) -> ApiResult<PageBean<Author>> {
28 let repo = AuthorRepository::new(state.db.clone());
29 let all = repo.get_authors(author_id, author_name.as_deref()).await?;
30 Ok(paginate(all, page, page_size))
31 }
32
33 #[tracing::instrument(skip_all, level = "debug")]
35 pub async fn get_manga_author_list(state: &AppState) -> ApiResult<Vec<Author>> {
36 AuthorRepository::new(state.db.clone())
37 .get_manga_author_list()
38 .await
39 }
40
41 #[tracing::instrument(skip_all, level = "debug")]
43 pub async fn get_author_manga(
44 state: &AppState,
45 page: i32,
46 page_size: i32,
47 id: i32,
48 ) -> ApiResult<PageBean<MangaListVo>> {
49 let (total, rows) = MangaRepository::new(state.db.clone())
50 .list_by_author_page(id, page, page_size)
51 .await?;
52 Ok(slice_rows(rows, total))
53 }
54
55 #[tracing::instrument(skip_all, level = "debug")]
57 pub async fn delete(state: &AppState, id: i32) -> ApiResult<()> {
58 let repo = AuthorRepository::new(state.db.clone());
59 if repo.get_related_manga(id).await? {
60 return Err(AppError::business("该作者已经绑定漫画了喵!"));
61 }
62 repo.delete_by_id(id).await
63 }
64
65 #[tracing::instrument(skip_all, level = "debug")]
67 pub async fn add(state: &AppState, author: Author) -> ApiResult<()> {
68 let repo = AuthorRepository::new(state.db.clone());
69 if let Some(name) = &author.author_name {
70 if repo.test_author_name(name).await?.is_some() {
71 return Err(AppError::unique("作者名"));
72 }
73 }
74 repo.insert(&author).await?;
75 Ok(())
76 }
77
78 #[tracing::instrument(skip_all, level = "debug")]
80 pub async fn get_author_by_id(state: &AppState, id: i32) -> ApiResult<Author> {
81 AuthorRepository::new(state.db.clone())
82 .get_author_by_id(id)
83 .await?
84 .ok_or_else(|| AppError::business("作者不存在喵"))
85 }
86
87 #[tracing::instrument(skip_all, level = "debug")]
89 pub async fn update_author(state: &AppState, author: Author) -> ApiResult<()> {
90 let id = author.id.ok_or_else(|| AppError::business("缺少作者 ID"))?;
91 let repo = AuthorRepository::new(state.db.clone());
92 repo.get_author_by_id(id)
93 .await?
94 .ok_or_else(|| AppError::business("作者不存在喵"))?;
95 if let Some(name) = &author.author_name {
96 if let Some(existing) = repo.test_author_name(name).await? {
97 if existing.id != Some(id) {
98 return Err(AppError::unique("作者名"));
99 }
100 }
101 }
102 repo.update_author(&author).await?;
103 on_author_or_magazine_renamed(state).await;
104 Ok(())
105 }
106}