pub struct EpisodeService;Expand description
话数服务
提供话数及关联数据(统计、发布)的完整业务逻辑。
Implementations§
Source§impl EpisodeService
impl EpisodeService
Sourcepub async fn select_list_by_manga_id(
state: &AppState,
manga_id: i32,
) -> ApiResult<Vec<EpisodeSimpleListVo>>
pub async fn select_list_by_manga_id( state: &AppState, manga_id: i32, ) -> ApiResult<Vec<EpisodeSimpleListVo>>
按漫画 ID 查询话数简单列表。
返回包含文件信息的精简话数列表,用于上传页展示。
结果按 manga_episode 升序排列,仅包含未删除的话数记录。
§返回值
返回漫画下所有未删除的话数列表,按 manga_episode 排序。
§Errors
AppError::Database— 数据库查询失败
§Examples
ⓘ
use tdm_server::service::episode_service::EpisodeService;
let episodes = EpisodeService::select_list_by_manga_id(&state, manga_id).await?;
for ep in &episodes {
println!("话数 {}: {}", ep.manga_episode, ep.manga_episode_name);
}Sourcepub async fn update_manga_episodes(
state: &AppState,
requests: Vec<PublishLinkRequest>,
) -> ApiResult<()>
pub async fn update_manga_episodes( state: &AppState, requests: Vec<PublishLinkRequest>, ) -> ApiResult<()>
批量更新话数发布链接。
接收一组发布链接请求,批量更新数据库中的链接字段。 更新完成后会刷新任务追踪缓存,并为每个话数触发 RSS 订阅源刷新。
§Errors
AppError::Database— 数据库更新失败
§Examples
ⓘ
let requests = vec![
PublishLinkRequest { id: 1, publish_link: Some("https://example.com/1".into()) },
PublishLinkRequest { id: 2, publish_link: Some("https://example.com/2".into()) },
];
EpisodeService::update_manga_episodes(&state, requests).await?;Sourcepub async fn update_publish_link(
state: &AppState,
id: i32,
publish_link: Option<String>,
) -> ApiResult<()>
pub async fn update_publish_link( state: &AppState, id: i32, publish_link: Option<String>, ) -> ApiResult<()>
Sourcepub async fn page_episode(
state: &AppState,
page: i32,
page_size: i32,
manga_id: i32,
) -> ApiResult<PageBean<EpisodeListVo>>
pub async fn page_episode( state: &AppState, page: i32, page_size: i32, manga_id: i32, ) -> ApiResult<PageBean<EpisodeListVo>>
Sourcepub async fn add_episodes(
state: &AppState,
dto: EpisodeEditDto,
) -> ApiResult<()>
pub async fn add_episodes( state: &AppState, dto: EpisodeEditDto, ) -> ApiResult<()>
新增话数(对齐 Java addEpisodes)。
支持两种模式:
- 批量模式:指定
manga_episode起始值和manga_episode_end结束值, 在区间内逐条创建话数。 - 单话模式:仅指定
manga_episode,创建一条话数记录。
创建完成后会刷新任务追踪缓存并触发 RSS 全量刷新。
§Errors
AppError::business("缺少漫画 ID")— DTO 中未提供manga_idAppError::business("起始话数格式不正确")— 话数序号不是有效整数AppError::business("结束话数格式不正确")— 结束序号不是有效整数AppError::business("该漫画单话已存在喵!")— 话数序号重复AppError::business("发布链接已存在喵")— 链接与其他话数冲突AppError::Database— 数据库操作失败
§Examples
ⓘ
// 批量创建话数 1~10
let dto = EpisodeEditDto {
manga_id: Some(100),
manga_episode: Some("1".into()),
manga_episode_end: Some("10".into()),
..Default::default()
};
EpisodeService::add_episodes(&state, dto).await?;
// 创建单话
let dto = EpisodeEditDto {
manga_id: Some(100),
manga_episode: Some("11".into()),
..Default::default()
};
EpisodeService::add_episodes(&state, dto).await?;Sourcepub async fn get_manga_episode_by_id(
state: &AppState,
id: i32,
) -> ApiResult<EpisodeDetailVo>
pub async fn get_manga_episode_by_id( state: &AppState, id: i32, ) -> ApiResult<EpisodeDetailVo>
Sourcepub async fn get_newest_manga_episode_by_id(
state: &AppState,
manga_id: i32,
) -> ApiResult<NewestEpisodeVo>
pub async fn get_newest_manga_episode_by_id( state: &AppState, manga_id: i32, ) -> ApiResult<NewestEpisodeVo>
Sourcepub async fn update_manga_episode(
state: &AppState,
dto: EpisodeEditDto,
) -> ApiResult<()>
pub async fn update_manga_episode( state: &AppState, dto: EpisodeEditDto, ) -> ApiResult<()>
Sourcepub async fn get_uploaded_submit(
state: &AppState,
page: i32,
page_size: i32,
manga_tran_name: Option<String>,
username: Option<String>,
) -> ApiResult<PageBean<UploadPageVo>>
pub async fn get_uploaded_submit( state: &AppState, page: i32, page_size: i32, manga_tran_name: Option<String>, username: Option<String>, ) -> ApiResult<PageBean<UploadPageVo>>
Sourcepub async fn get_statistics(
state: &AppState,
start: &str,
end: &str,
) -> ApiResult<Statistics>
pub async fn get_statistics( state: &AppState, start: &str, end: &str, ) -> ApiResult<Statistics>
任意时间段统计
Sourcepub async fn get_statistics_list(state: &AppState) -> ApiResult<Vec<Statistics>>
pub async fn get_statistics_list(state: &AppState) -> ApiResult<Vec<Statistics>>
预设时间段统计列表(6 项:日/月/年 + 上期对比)
Sourcepub async fn get_member_statistics(
state: &AppState,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> ApiResult<Vec<MemberStatistics>>
pub async fn get_member_statistics( state: &AppState, start: DateTime<Utc>, end: DateTime<Utc>, ) -> ApiResult<Vec<MemberStatistics>>
组员完成统计
Sourcepub async fn rollback_episode(
state: &AppState,
episode_id: i32,
workflow_type: &str,
) -> ApiResult<()>
pub async fn rollback_episode( state: &AppState, episode_id: i32, workflow_type: &str, ) -> ApiResult<()>
回退流程
Sourcepub async fn upload_manga_file(
state: &AppState,
data: Bytes,
episode_id: i32,
my_name: &str,
manga_id: i32,
original_filename: &str,
) -> ApiResult<()>
pub async fn upload_manga_file( state: &AppState, data: Bytes, episode_id: i32, my_name: &str, manga_id: i32, original_filename: &str, ) -> ApiResult<()>
上传话数工作文件(对齐 Java MangaFileUtils + 更新 DB 路径)
Sourcepub async fn download_episode_file(
state: &AppState,
req: EpisodeDownloadRequest,
) -> ApiResult<(String, Bytes)>
pub async fn download_episode_file( state: &AppState, req: EpisodeDownloadRequest, ) -> ApiResult<(String, Bytes)>
下载话数工作文件(legacy 路径 → 规范目录 → OSS 回退)
Auto Trait Implementations§
impl Freeze for EpisodeService
impl RefUnwindSafe for EpisodeService
impl Send for EpisodeService
impl Sync for EpisodeService
impl Unpin for EpisodeService
impl UnsafeUnpin for EpisodeService
impl UnwindSafe for EpisodeService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
Wrap the input message
T in a tonic::Request