tdm_server_rust/repository/
author_repo.rs1use crate::db::DbConn;
6use crate::entity::{author::Author, manga::Manga};
7use crate::sea_entity::{authortb, mangaauthor, mangatb};
8use sea_orm::{
9 ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, JoinType, PaginatorTrait,
10 QueryFilter, QueryOrder, QuerySelect, RelationTrait, Set,
11};
12use sqlx::postgres::PgPool;
13
14pub struct AuthorRepository {
16 db: DbConn,
18}
19
20impl AuthorRepository {
21 pub fn new(pool: PgPool) -> Self {
23 Self {
24 db: crate::db::from_sqlx_pool(pool),
25 }
26 }
27
28 pub fn from_db(db: DatabaseConnection) -> Self {
30 Self { db }
31 }
32
33 #[tracing::instrument(skip_all, level = "debug")]
35 pub async fn get_authors(
36 &self,
37 author_id: Option<i16>,
38 author_name: Option<&str>,
39 ) -> crate::error::ApiResult<Vec<Author>> {
40 let mut q = authortb::Entity::find();
41 if let Some(id) = author_id {
42 q = q.filter(authortb::Column::Id.eq(id as i32));
43 }
44 if let Some(name) = author_name {
45 q = q.filter(authortb::Column::AuthorName.eq(name));
46 }
47 let rows = q.all(&self.db).await?;
48 Ok(rows.into_iter().map(model_to_author).collect())
49 }
50
51 #[tracing::instrument(skip_all, level = "debug")]
53 pub async fn delete_by_id(&self, id: i32) -> crate::error::ApiResult<()> {
54 authortb::Entity::delete_by_id(id).exec(&self.db).await?;
55 Ok(())
56 }
57
58 #[tracing::instrument(skip_all, level = "debug")]
60 pub async fn insert(&self, author: &Author) -> crate::error::ApiResult<i32> {
61 let name = author
62 .author_name
63 .as_deref()
64 .ok_or_else(|| crate::error::AppError::business("作者名不能为空"))?;
65 let model = authortb::ActiveModel {
66 author_name: Set(name.to_string()),
67 ..Default::default()
68 };
69 let inserted = model.insert(&self.db).await?;
70 Ok(inserted.id)
71 }
72
73 #[tracing::instrument(skip_all, level = "debug")]
75 pub async fn get_author_by_id(&self, id: i32) -> crate::error::ApiResult<Option<Author>> {
76 let row = authortb::Entity::find_by_id(id).one(&self.db).await?;
77 Ok(row.map(model_to_author))
78 }
79
80 #[tracing::instrument(skip_all, level = "debug")]
82 pub async fn update_author(&self, author: &Author) -> crate::error::ApiResult<()> {
83 let id = author
84 .id
85 .ok_or_else(|| crate::error::AppError::business("作者 ID 不能为空"))?;
86 let name = author
87 .author_name
88 .as_deref()
89 .ok_or_else(|| crate::error::AppError::business("作者名不能为空"))?;
90 let model = authortb::ActiveModel {
91 id: Set(id),
92 author_name: Set(name.to_string()),
93 };
94 model.update(&self.db).await?;
95 Ok(())
96 }
97
98 #[tracing::instrument(skip_all, level = "debug")]
100 pub async fn test_author_name(
101 &self,
102 author_name: &str,
103 ) -> crate::error::ApiResult<Option<Author>> {
104 let row = authortb::Entity::find()
105 .filter(authortb::Column::AuthorName.eq(author_name))
106 .one(&self.db)
107 .await?;
108 Ok(row.map(model_to_author))
109 }
110
111 #[tracing::instrument(skip_all, level = "debug")]
113 pub async fn get_related_manga(&self, id: i32) -> crate::error::ApiResult<bool> {
114 let n = mangaauthor::Entity::find()
115 .filter(mangaauthor::Column::AuthorId.eq(id))
116 .count(&self.db)
117 .await?;
118 Ok(n > 0)
119 }
120
121 #[tracing::instrument(skip_all, level = "debug")]
123 pub async fn get_max_author_id(&self) -> crate::error::ApiResult<Option<i32>> {
124 let row = authortb::Entity::find()
125 .order_by_desc(authortb::Column::Id)
126 .one(&self.db)
127 .await?;
128 Ok(row.map(|r| r.id))
129 }
130
131 #[tracing::instrument(skip_all, level = "debug")]
133 pub async fn get_manga_author_list(&self) -> crate::error::ApiResult<Vec<Author>> {
134 let rows = authortb::Entity::find().all(&self.db).await?;
135 Ok(rows.into_iter().map(model_to_author).collect())
136 }
137
138 #[tracing::instrument(skip_all, level = "debug")]
140 pub async fn get_author_manga(&self, id: i32) -> crate::error::ApiResult<Vec<Manga>> {
141 let rows = mangatb::Entity::find()
142 .join(
143 JoinType::InnerJoin,
144 mangaauthor::Relation::Mangatb.def().rev(),
145 )
146 .filter(mangaauthor::Column::AuthorId.eq(id))
147 .distinct()
148 .order_by_desc(mangatb::Column::UpdateTime)
149 .all(&self.db)
150 .await?;
151 Ok(rows.into_iter().map(model_to_manga).collect())
152 }
153}
154
155fn model_to_author(m: authortb::Model) -> Author {
157 Author {
158 id: Some(m.id),
159 author_name: Some(m.author_name),
160 }
161}
162
163fn model_to_manga(m: mangatb::Model) -> Manga {
165 Manga {
166 id: Some(m.id),
167 manga_tran_name: Some(m.manga_tran_name),
168 manga_ori_name: Some(m.manga_ori_name),
169 category: Some(m.category as i16),
170 manga_status: Some(m.manga_status as i16),
171 img_url: Some(m.image),
172 link: m.link,
173 introduction: m.introduction,
174 update_time: Some(m.update_time.and_utc()),
175 }
176}