Skip to main content

tdm_server_rust/service/
author_service.rs

1//! 作者业务服务 (Author Service)
2//!
3//! 作者信息的增删改查及关联漫画查询。
4
5use crate::{
6    app::AppState,
7    common::PageBean,
8    entity::{author::Author, manga::MangaListVo},
9    error::{ApiResult, AppError},
10    repository::{author_repo::AuthorRepository, manga_repo::MangaRepository},
11    utils::page::paginate,
12};
13
14/// 作者服务
15pub struct AuthorService;
16
17impl AuthorService {
18    /// 分页查询作者
19    #[tracing::instrument(skip_all, level = "debug")]
20    pub async fn get_authors(
21        state: &AppState,
22        page: i32,
23        page_size: i32,
24        author_id: Option<i16>,
25        author_name: Option<String>,
26    ) -> ApiResult<PageBean<Author>> {
27        let repo = AuthorRepository::new(state.db.clone());
28        let all = repo
29            .get_authors(author_id, author_name.as_deref())
30            .await?;
31        Ok(paginate(all, page, page_size))
32    }
33
34    /// 全量作者列表
35    #[tracing::instrument(skip_all, level = "debug")]
36    pub async fn get_manga_author_list(state: &AppState) -> ApiResult<Vec<Author>> {
37        AuthorRepository::new(state.db.clone())
38            .get_manga_author_list()
39            .await
40    }
41
42    /// 查询作者所著漫画
43    #[tracing::instrument(skip_all, level = "debug")]
44    pub async fn get_author_manga(
45        state: &AppState,
46        page: i32,
47        page_size: i32,
48        id: i32,
49    ) -> ApiResult<PageBean<MangaListVo>> {
50        MangaRepository::new(state.db.clone())
51            .list_by_author(id)
52            .await
53            .map(|all| paginate(all, page, page_size))
54    }
55
56    /// 删除作者
57    #[tracing::instrument(skip_all, level = "debug")]
58    pub async fn delete(state: &AppState, id: i32) -> ApiResult<()> {
59        let repo = AuthorRepository::new(state.db.clone());
60        if repo.get_related_manga(id).await? {
61            return Err(AppError::business("该作者已经绑定漫画了喵!"));
62        }
63        repo.delete_by_id(id).await
64    }
65
66    /// 新增作者
67    #[tracing::instrument(skip_all, level = "debug")]
68    pub async fn add(state: &AppState, author: Author) -> ApiResult<()> {
69        let repo = AuthorRepository::new(state.db.clone());
70        if let Some(name) = &author.author_name {
71            if repo.test_author_name(name).await?.is_some() {
72                return Err(AppError::unique("作者名"));
73            }
74        }
75        repo.insert(&author).await?;
76        Ok(())
77    }
78
79    /// 按 ID 查询作者
80    #[tracing::instrument(skip_all, level = "debug")]
81    pub async fn get_author_by_id(state: &AppState, id: i32) -> ApiResult<Author> {
82        AuthorRepository::new(state.db.clone())
83            .get_author_by_id(id)
84            .await?
85            .ok_or_else(|| AppError::business("作者不存在喵"))
86    }
87
88    /// 更新作者
89    #[tracing::instrument(skip_all, level = "debug")]
90    pub async fn update_author(state: &AppState, author: Author) -> ApiResult<()> {
91        let id = author
92            .id
93            .ok_or_else(|| AppError::business("缺少作者 ID"))?;
94        let repo = AuthorRepository::new(state.db.clone());
95        repo.get_author_by_id(id)
96            .await?
97            .ok_or_else(|| AppError::business("作者不存在喵"))?;
98        if let Some(name) = &author.author_name {
99            if let Some(existing) = repo.test_author_name(name).await? {
100                if existing.id != Some(id) {
101                    return Err(AppError::unique("作者名"));
102                }
103            }
104        }
105        repo.update_author(&author).await
106    }
107}