1use crate::utils::query_deserialize::{
7 de_opt_i16, de_opt_i32, de_opt_string, de_page, de_page_size,
8};
9use crate::{
10 common::AppJson,
11 app::AppState,
12 common::{page_bean::PageBean, result::ResultBody},
13 entity::member::{
14 MemberAddRequest, MemberCache, MemberEpisode, MemberEpisodeVo, MemberInfoVo, MemberListVo,
15 MemberSelfUpdateRequest, MemberUpdateRequest, ResetPassword, StationedManga,
16 },
17 error::{ApiResult, AppError},
18 middleware::AuthMember,
19 service::member_service::MemberService,
20};
21use axum::{
22 extract::{Extension, Path, Query, State},
23 routing::{get, patch, put},
24 Router,
25};
26use serde::Deserialize;
27
28#[derive(Debug, Deserialize)]
30#[serde(rename_all = "camelCase")]
31pub struct MemberPageQuery {
32 #[serde(default, deserialize_with = "de_page")]
34 pub page: i32,
35 #[serde(default, deserialize_with = "de_page_size")]
37 pub page_size: i32,
38 #[serde(default, deserialize_with = "de_opt_string")]
40 pub username: Option<String>,
41 #[serde(default, deserialize_with = "de_opt_i16")]
43 pub post: Option<i16>,
44 #[serde(default, deserialize_with = "de_opt_i16")]
46 pub intern: Option<i16>,
47 #[serde(default, deserialize_with = "de_opt_string")]
49 pub email: Option<String>,
50}
51
52#[derive(Debug, Deserialize)]
54#[serde(rename_all = "camelCase")]
55pub struct MemberEpisodePageQuery {
56 #[serde(default, deserialize_with = "de_page")]
58 pub page: i32,
59 #[serde(default, deserialize_with = "de_page_size")]
61 pub page_size: i32,
62 #[serde(default, deserialize_with = "de_opt_i32")]
64 pub id: Option<i32>,
65}
66
67pub fn routes() -> Router<AppState> {
69 Router::new()
70 .route("/", get(page_member).post(new_member).put(update_member))
71 .route("/all", get(get_member_list))
72 .route("/self", put(update_member_self))
73 .route("/updatepwd", patch(update_member_password))
74 .route("/memberepisode", get(page_episode))
75 .route("/takeEpisode", patch(take_episode))
76 .route("/submitEpisode", patch(submit_episode))
77 .route("/stationedMangas/:id", get(find_stationed_mangas))
78 .route("/:id", get(get_member_by_id).delete(delete_member))
79}
80
81#[tracing::instrument(skip_all, level = "info")]
83pub async fn page_member(
84 State(state): State<AppState>,
85 Query(q): Query<MemberPageQuery>,
86) -> ApiResult<ResultBody<PageBean<MemberListVo>>> {
87 let data = MemberService::page(
88 &state,
89 q.page,
90 q.page_size,
91 q.username,
92 q.post,
93 q.intern,
94 q.email,
95 )
96 .await?;
97 Ok(ResultBody::success_data(data))
98}
99
100#[tracing::instrument(skip_all, level = "info")]
102pub async fn get_member_list(
103 State(state): State<AppState>,
104) -> ApiResult<ResultBody<Vec<MemberCache>>> {
105 let data = MemberService::get_member_list(&state).await?;
106 Ok(ResultBody::success_data(data))
107}
108
109#[tracing::instrument(skip_all, level = "info")]
111pub async fn delete_member(
112 State(state): State<AppState>,
113 Path(id): Path<String>,
114) -> ApiResult<ResultBody<()>> {
115 let id_list: Vec<i32> = id
116 .split(',')
117 .filter_map(|s| s.trim().parse().ok())
118 .collect();
119 MemberService::delete(&state, id_list).await?;
120 Ok(ResultBody::success())
121}
122
123#[tracing::instrument(skip_all, level = "info")]
125pub async fn new_member(
126 State(state): State<AppState>,
127 AppJson(body): AppJson<MemberAddRequest>,
128) -> ApiResult<ResultBody<()>> {
129 MemberService::new_member(&state, body).await?;
130 Ok(ResultBody::success())
131}
132
133#[tracing::instrument(skip_all, level = "info")]
135pub async fn get_member_by_id(
136 State(state): State<AppState>,
137 Path(id): Path<String>,
138) -> ApiResult<ResultBody<MemberInfoVo>> {
139 let id: i32 = id
140 .parse()
141 .map_err(|_| crate::error::AppError::business("无效的组员 ID 喵"))?;
142 let m = MemberService::get_member_by_id(&state, id).await?;
143 Ok(ResultBody::success_data(MemberInfoVo::from(m)))
144}
145
146#[tracing::instrument(skip_all, level = "info")]
148pub async fn update_member(
149 State(state): State<AppState>,
150 AppJson(body): AppJson<MemberUpdateRequest>,
151) -> ApiResult<ResultBody<()>> {
152 MemberService::update_member(&state, body).await?;
153 Ok(ResultBody::success())
154}
155
156#[tracing::instrument(skip_all, level = "info")]
158pub async fn update_member_self(
159 State(state): State<AppState>,
160 AppJson(body): AppJson<MemberSelfUpdateRequest>,
161) -> ApiResult<ResultBody<()>> {
162 MemberService::update_member_self(&state, body).await?;
163 Ok(ResultBody::success())
164}
165
166#[tracing::instrument(skip_all, level = "info")]
168pub async fn find_stationed_mangas(
169 State(state): State<AppState>,
170 Path(id): Path<String>,
171) -> ApiResult<ResultBody<Vec<StationedManga>>> {
172 let id: i32 = id
173 .parse()
174 .map_err(|_| AppError::business("无效的组员 ID 喵"))?;
175 let data = MemberService::find_stationed_mangas(&state, id).await?;
176 Ok(ResultBody::success_data(data))
177}
178
179#[tracing::instrument(skip_all, level = "info")]
181pub async fn update_member_password(
182 State(state): State<AppState>,
183 AppJson(body): AppJson<ResetPassword>,
184) -> ApiResult<ResultBody<()>> {
185 MemberService::update_member_password(&state, body).await?;
186 Ok(ResultBody::success())
187}
188
189#[tracing::instrument(skip_all, level = "info")]
191pub async fn page_episode(
192 State(state): State<AppState>,
193 Query(q): Query<MemberEpisodePageQuery>,
194) -> ApiResult<ResultBody<PageBean<MemberEpisodeVo>>> {
195 let id = q.id.ok_or_else(|| AppError::business("无效的组员 ID 喵"))?;
196 let page = MemberService::page_episode(&state, q.page, q.page_size, id).await?;
197 Ok(ResultBody::success_data(page))
198}
199
200#[tracing::instrument(skip_all, level = "info")]
202pub async fn take_episode(
203 State(state): State<AppState>,
204 Extension(AuthMember(_member)): Extension<AuthMember>,
205 AppJson(body): AppJson<MemberEpisode>,
206) -> ApiResult<ResultBody<()>> {
207 MemberService::take_episode(&state, body).await?;
208 Ok(ResultBody::success())
209}
210
211#[tracing::instrument(skip_all, level = "info")]
213pub async fn submit_episode(
214 State(state): State<AppState>,
215 Extension(AuthMember(_member)): Extension<AuthMember>,
216 AppJson(body): AppJson<MemberEpisode>,
217) -> ApiResult<ResultBody<()>> {
218 MemberService::submit_episode(&state, body).await?;
219 Ok(ResultBody::success())
220}