提取service

This commit is contained in:
胡天 2024-02-02 15:43:11 +08:00
parent d40998f917
commit 246c17ba39
5 changed files with 125 additions and 85 deletions

View File

@ -1,26 +1,13 @@
use std::sync::Arc;
use askama::Template; use askama::Template;
use axum::extract::{Path, Query, State}; use axum::extract::{Path, Query, State};
use axum::Form; use axum::Form;
use axum::http::{header, HeaderMap, StatusCode}; use axum::http::{HeaderMap, StatusCode};
use axum::response::Html; use axum::response::Html;
use serde::Deserialize; use serde::Deserialize;
use crate::{db::member, err::Error, form, model, model::state::AppState, Result, view}; use crate::{err::Error, form, model::state::AppState, Result, view};
use crate::service::MemberService;
fn get_conn(state: &AppState) -> Arc<sqlx::MySqlPool> { use crate::util::redirect;
state.pool.clone()
}
fn redirect(url: &str) -> Result<(StatusCode, HeaderMap, ())> {
let mut header = HeaderMap::new();
header.insert(header::LOCATION, url.parse().unwrap());
Ok((StatusCode::FOUND, header, ()))
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct PageQuery { pub struct PageQuery {
@ -33,11 +20,7 @@ pub async fn index(
State(state): State<AppState>, State(state): State<AppState>,
Query(q): Query<PageQuery>, Query(q): Query<PageQuery>,
) -> Result<Html<String>> { ) -> Result<Html<String>> {
let conn = get_conn(&state); let tpl = MemberService::index(&state, q).await?;
let p = member::list(&conn, q.page.unwrap_or(0)).await?;
let tpl = view::Home { p, msg: q.msg };
let html = tpl.render().map_err(Error::from)?; let html = tpl.render().map_err(Error::from)?;
Ok(Html(html)) Ok(Html(html))
} }
@ -46,18 +29,9 @@ pub async fn detail(
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<u32>, Path(id): Path<u32>,
) -> Result<Html<String>> { ) -> Result<Html<String>> {
let conn = get_conn(&state); let tpl = MemberService::detail(&state, id).await?;
let html = tpl.render().map_err(Error::from)?;
let m = member::find(&conn, id).await?; Ok(Html(html))
match m {
None => Err(Error::not_found("不存在的会员")),
Some(m) => {
let tpl = view::Detail { m };
let html = tpl.render().map_err(Error::from)?;
Ok(Html(html))
}
}
} }
@ -72,16 +46,7 @@ pub async fn add(
State(state): State<AppState>, State(state): State<AppState>,
Form(frm): Form<form::AddAndEdit>, Form(frm): Form<form::AddAndEdit>,
) -> Result<(StatusCode, HeaderMap, ())> { ) -> Result<(StatusCode, HeaderMap, ())> {
let conn = get_conn(&state); MemberService::add(&state, frm).await?;
member::add(&conn, &model::member::Member {
name: frm.name,
balance: frm.balance,
types: frm.types,
dateline: chrono::Local::now(),
..Default::default()
}).await?;
redirect("/?msg=会员添加成功") redirect("/?msg=会员添加成功")
} }
@ -90,18 +55,9 @@ pub async fn edit_ui(
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<u32>, Path(id): Path<u32>,
) -> Result<Html<String>> { ) -> Result<Html<String>> {
let conn = get_conn(&state); let tpl = MemberService::edit_ui(&state, id).await?;
let html = tpl.render().map_err(Error::from)?;
let m = member::find(&conn, id).await?; Ok(Html(html))
match m {
Some(m) => {
let tpl = view::Edit { m };
let html = tpl.render().map_err(Error::from)?;
Ok(Html(html))
}
None => Err(Error::not_found("不存在的会员")),
}
} }
@ -110,16 +66,7 @@ pub async fn edit(
Path(id): Path<u32>, Path(id): Path<u32>,
Form(frm): Form<form::AddAndEdit>, Form(frm): Form<form::AddAndEdit>,
) -> Result<(StatusCode, HeaderMap, ())> { ) -> Result<(StatusCode, HeaderMap, ())> {
let conn = get_conn(&state); MemberService::edit(&state, id, frm).await?;
member::edit(&conn, &model::member::Member {
id,
name: frm.name,
balance: frm.balance,
types: frm.types,
..Default::default()
}).await?;
redirect("/?msg=会员修改成功") redirect("/?msg=会员修改成功")
} }
@ -127,10 +74,7 @@ pub async fn del(
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<u32>, Path(id): Path<u32>,
) -> Result<(StatusCode, HeaderMap, ())> { ) -> Result<(StatusCode, HeaderMap, ())> {
let conn = get_conn(&state); MemberService::del(&state, id).await?;
member::del(&conn, id).await?;
redirect("/?msg=逻辑删除成功") redirect("/?msg=逻辑删除成功")
} }
@ -138,10 +82,7 @@ pub async fn real_del(
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<u32>, Path(id): Path<u32>,
) -> Result<(StatusCode, HeaderMap, ())> { ) -> Result<(StatusCode, HeaderMap, ())> {
let conn = get_conn(&state); MemberService::real_del(&state, id).await?;
member::real_del(&conn, id).await?;
redirect("/?msg=物理删除成功") redirect("/?msg=物理删除成功")
} }
@ -157,15 +98,7 @@ pub async fn tran(
State(state): State<AppState>, State(state): State<AppState>,
Form(frm): Form<form::Tran>, Form(frm): Form<form::Tran>,
) -> Result<(StatusCode, HeaderMap, ())> { ) -> Result<(StatusCode, HeaderMap, ())> {
let conn = get_conn(&state); let aff = MemberService::tran(&state, frm).await?;
let aff = member::tran(&conn, &model::member::Tran {
from_member: frm.from_member,
to_member: frm.to_member,
amount: frm.amount,
}).await?;
tracing::debug!("{:?}", aff); tracing::debug!("{:?}", aff);
redirect("/?msg=转账成功") redirect("/?msg=转账成功")
} }

View File

@ -6,5 +6,6 @@ pub mod model;
pub mod view; pub mod view;
pub mod form; pub mod form;
pub mod util; pub mod util;
pub mod service;
pub type Result<T> = std::result::Result<T, crate::err::Error>; pub type Result<T> = std::result::Result<T, crate::err::Error>;

83
src/service/member.rs Normal file
View File

@ -0,0 +1,83 @@
use crate::{form, model, view, util, Result};
use crate::db::member;
use crate::err::Error;
use crate::handler::PageQuery;
use crate::model::state::AppState;
pub struct MemberService;
impl MemberService {
pub async fn index(state: &AppState, q: PageQuery) -> Result<view::Home> {
let conn = util::get_conn(&state);
let p = member::list(&conn, q.page.unwrap_or(0)).await?;
return Ok(view::Home { p, msg: q.msg });
}
pub async fn detail(state: &AppState, id: u32) -> Result<view::Detail> {
let conn = util::get_conn(&state);
let m = member::find(&conn, id).await?;
match m {
None => Err(Error::not_found("不存在的会员")),
Some(m) => Ok(view::Detail { m })
}
}
pub async fn add(state: &AppState, frm: form::AddAndEdit) -> Result<u32> {
let conn = util::get_conn(&state);
member::add(&conn, &model::member::Member {
name: frm.name,
balance: frm.balance,
types: frm.types,
dateline: chrono::Local::now(),
..Default::default()
}).await
}
pub async fn edit(state: &AppState, id: u32, frm: form::AddAndEdit) -> Result<u64> {
let conn = util::get_conn(&state);
member::edit(&conn, &model::member::Member {
id,
name: frm.name,
balance: frm.balance,
types: frm.types,
..Default::default()
}).await
}
pub async fn edit_ui(state: &AppState, id: u32) -> Result<view::Edit> {
let conn = util::get_conn(&state);
let m = member::find(&conn, id).await?;
match m {
None => Err(Error::not_found("不存在的会员")),
Some(m) => Ok(view::Edit { m })
}
}
pub async fn del(state: &AppState, id: u32) -> Result<u64> {
let conn = util::get_conn(&state);
member::del(&conn, id).await
}
pub async fn real_del(state: &AppState, id: u32) -> Result<u64> {
let conn = util::get_conn(&state);
member::real_del(&conn, id).await
}
pub async fn tran(state: &AppState, frm: form::Tran) -> Result<(u64, u64)> {
let conn = util::get_conn(&state);
member::tran(&conn, &model::member::Tran {
from_member: frm.from_member,
to_member: frm.to_member,
amount: frm.amount,
}).await
}
}

6
src/service/mod.rs Normal file
View File

@ -0,0 +1,6 @@
mod member;
pub use member::*;

View File

@ -1,8 +1,24 @@
use std::sync::Arc;
use axum::http::{header, HeaderMap, StatusCode};
use crate::model::state::AppState;
pub fn get_conn(state: &AppState) -> Arc<sqlx::MySqlPool> {
state.pool.clone()
}
pub fn redirect(url: &str) -> crate::Result<(StatusCode, HeaderMap, ())> {
let mut header = HeaderMap::new();
header.insert(header::LOCATION, url.parse().unwrap());
Ok((StatusCode::FOUND, header, ()))
}
pub mod default_datetime_format { pub mod default_datetime_format {
use chrono::{DateTime, Local, NaiveDateTime}; use chrono::{DateTime, Local, NaiveDateTime};
use serde::{self, Deserialize, Serializer, Deserializer}; use serde::{self, Deserialize, Deserializer, Serializer};
const FORMAT: &'static str = "%Y-%m-%d %H:%M:%S"; const FORMAT: &'static str = "%Y-%m-%d %H:%M:%S";
@ -16,6 +32,7 @@ pub mod default_datetime_format {
let s = format!("{}", date.format(FORMAT)); let s = format!("{}", date.format(FORMAT));
serializer.serialize_str(&s) serializer.serialize_str(&s)
} }
pub fn deserialize<'de, D>( pub fn deserialize<'de, D>(
deserializer: D, deserializer: D,
) -> Result<DateTime<Local>, D::Error> ) -> Result<DateTime<Local>, D::Error>
@ -23,7 +40,7 @@ pub mod default_datetime_format {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let datetime_str = String::deserialize(deserializer)?; let datetime_str = String::deserialize(deserializer)?;
let dt = NaiveDateTime::parse_from_str(&datetime_str, FORMAT).map_err(serde::de::Error::custom)?; let dt = NaiveDateTime::parse_from_str(&datetime_str, FORMAT).map_err(serde::de::Error::custom)?;
Ok(dt.and_local_timezone(Local).unwrap()) Ok(dt.and_local_timezone(Local).unwrap())
} }
} }