tdm_server_rust/repository/
editor_page_repo.rs1use crate::db::DbConn;
7use crate::error::ApiResult;
8use crate::sea_entity::editor_page;
9use sea_orm::{
10 ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseConnection, EntityTrait,
11 PaginatorTrait, QueryFilter, QueryOrder, Set,
12};
13use sqlx::postgres::PgPool;
14
15#[derive(Debug, Clone)]
17pub struct NewEditorPage {
18 pub page_index: i32,
20 pub source_oss_id: Option<i32>,
22 pub source_file_name: Option<String>,
24 pub image_object_key: String,
26 pub image_bucket: Option<String>,
28 pub image_url: String,
30 pub image_width: Option<i32>,
32 pub image_height: Option<i32>,
34}
35
36pub struct EditorPageRepository {
38 db: DbConn,
40}
41
42impl EditorPageRepository {
43 pub fn new(pool: PgPool) -> Self {
45 Self {
46 db: crate::db::from_sqlx_pool(pool),
47 }
48 }
49
50 pub fn from_db(db: DatabaseConnection) -> Self {
52 Self { db }
53 }
54
55 #[tracing::instrument(skip_all, level = "debug")]
57 pub async fn list_by_episode(&self, episode_id: i32) -> ApiResult<Vec<editor_page::Model>> {
58 Self::list_by_episode_with(&self.db, episode_id).await
59 }
60
61 pub async fn list_by_episode_with<C: ConnectionTrait>(
63 db: &C,
64 episode_id: i32,
65 ) -> ApiResult<Vec<editor_page::Model>> {
66 let rows = editor_page::Entity::find()
67 .filter(editor_page::Column::EpisodeId.eq(episode_id))
68 .order_by_asc(editor_page::Column::PageIndex)
69 .all(db)
70 .await?;
71 Ok(rows)
72 }
73
74 #[tracing::instrument(skip_all, level = "debug")]
76 pub async fn count_by_episode(&self, episode_id: i32) -> ApiResult<u64> {
77 let n = editor_page::Entity::find()
78 .filter(editor_page::Column::EpisodeId.eq(episode_id))
79 .count(&self.db)
80 .await?;
81 Ok(n)
82 }
83
84 #[tracing::instrument(skip_all, level = "debug")]
86 pub async fn delete_by_episode(&self, episode_id: i32) -> ApiResult<Vec<i64>> {
87 Self::delete_by_episode_with(&self.db, episode_id).await
88 }
89
90 pub async fn delete_by_episode_with<C: ConnectionTrait>(
92 db: &C,
93 episode_id: i32,
94 ) -> ApiResult<Vec<i64>> {
95 let ids: Vec<i64> = editor_page::Entity::find()
96 .filter(editor_page::Column::EpisodeId.eq(episode_id))
97 .all(db)
98 .await?
99 .into_iter()
100 .map(|m| m.id)
101 .collect();
102 editor_page::Entity::delete_many()
103 .filter(editor_page::Column::EpisodeId.eq(episode_id))
104 .exec(db)
105 .await?;
106 Ok(ids)
107 }
108
109 #[tracing::instrument(skip_all, level = "debug")]
111 pub async fn insert_pages(
112 &self,
113 episode_id: i32,
114 pages: Vec<NewEditorPage>,
115 ) -> ApiResult<Vec<editor_page::Model>> {
116 Self::insert_pages_with(&self.db, episode_id, pages).await
117 }
118
119 pub async fn insert_pages_with<C: ConnectionTrait>(
121 db: &C,
122 episode_id: i32,
123 pages: Vec<NewEditorPage>,
124 ) -> ApiResult<Vec<editor_page::Model>> {
125 if pages.is_empty() {
126 return Ok(Vec::new());
127 }
128 let models: Vec<editor_page::ActiveModel> = pages
129 .into_iter()
130 .map(|p| editor_page::ActiveModel {
131 episode_id: Set(episode_id),
132 page_index: Set(p.page_index),
133 source_oss_id: Set(p.source_oss_id),
134 source_file_name: Set(p.source_file_name),
135 image_object_key: Set(p.image_object_key),
136 image_bucket: Set(p.image_bucket),
137 image_url: Set(p.image_url),
138 image_width: Set(p.image_width),
139 image_height: Set(p.image_height),
140 uploaded: Set(true),
141 ..Default::default()
142 })
143 .collect();
144 editor_page::Entity::insert_many(models).exec(db).await?;
145 Self::list_by_episode_with(db, episode_id).await
146 }
147
148 #[tracing::instrument(skip_all, level = "debug")]
150 pub async fn episode_of_page(&self, page_id: i64) -> ApiResult<Option<i32>> {
151 let row = editor_page::Entity::find_by_id(page_id)
152 .one(&self.db)
153 .await?;
154 Ok(row.map(|m| m.episode_id))
155 }
156
157 #[tracing::instrument(skip_all, level = "debug")]
159 pub async fn set_translation_completed(&self, page_id: i64, completed: bool) -> ApiResult<()> {
160 let Some(model) = editor_page::Entity::find_by_id(page_id)
161 .one(&self.db)
162 .await?
163 else {
164 return Err(crate::error::AppError::business(format!(
165 "页面 {page_id} 不存在喵"
166 )));
167 };
168 let mut am: editor_page::ActiveModel = model.into();
169 am.translation_completed = Set(completed);
170 am.updated_at = Set(chrono::Utc::now().naive_utc());
171 am.update(&self.db).await?;
172 Ok(())
173 }
174}