Responsable宏添加泛型支持

This commit is contained in:
李运家 2024-10-12 19:25:37 +08:00
parent aeec41f083
commit dfe586c231
7 changed files with 58 additions and 117 deletions

View File

@ -1,5 +1,4 @@
pub mod entities; pub mod entities;
pub mod dto; pub mod dto;
pub mod vo; pub mod vo;
pub mod pageable;
pub mod db_result; pub mod db_result;

View File

@ -1,33 +1,33 @@
use macros::Responsable; // use macros::Responsable;
use serde::Serialize; // use serde::Serialize;
use crate::entities::feedback::Feedback; // use crate::entities::feedback::Feedback;
#[derive(Debug, Serialize, Responsable)] // #[derive(Debug, Serialize, Responsable)]
pub struct FeedbackPageable { // pub struct FeedbackPageable {
pub data: Vec<Feedback>, // pub data: Vec<Feedback>,
pub total: i64, // pub total: i64,
pub page: i64, // pub page: i64,
#[serde(rename = "pageSize")] // #[serde(rename = "pageSize")]
pub page_size: i64, // pub page_size: i64,
} // }
impl FeedbackPageable { // impl FeedbackPageable {
pub fn new(data: Vec<Feedback>, total: i64, page: i64, page_size: i64) -> Self { // pub fn new(data: Vec<Feedback>, total: i64, page: i64, page_size: i64) -> Self {
FeedbackPageable { // FeedbackPageable {
data, // data,
total, // total,
page, // page,
page_size, // page_size,
} // }
} // }
pub fn empty(page: i64, page_size: i64) -> Self { // pub fn empty(page: i64, page_size: i64) -> Self {
FeedbackPageable { // FeedbackPageable {
data: vec![], // data: vec![],
total: 0, // total: 0,
page, // page,
page_size, // page_size,
} // }
} // }
} // }

View File

@ -1,2 +1,3 @@
pub mod account; pub mod account;
pub mod feedback; pub mod feedback;
pub mod pageable;

View File

@ -1,23 +1,20 @@
use serde::Serialize; use macros::Responsable;
use std::fmt::Debug; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize)] #[derive(Debug, Serialize, Deserialize, Responsable)]
pub struct Pageable<T> pub struct Pageable<D>
where where
T: Debug + Serialize, D: Serialize,
{ {
pub data: Vec<T>, pub data: Vec<D>,
pub total: i64, pub total: i64,
pub page: i64, pub page: i64,
#[serde(rename = "pageSize")] #[serde(rename = "pageSize")]
pub page_size: i64, pub page_size: i64,
} }
impl<T> Pageable<T> impl <D> Pageable<D> where D: Serialize {
where pub fn new(data: Vec<D>, total: i64, page: i64, page_size: i64) -> Self {
T: Debug + Serialize,
{
pub fn new(data: Vec<T>, total: i64, page: i64, page_size: i64) -> Self {
Pageable { Pageable {
data, data,
total, total,
@ -25,7 +22,6 @@ where
page_size, page_size,
} }
} }
pub fn empty(page: i64, page_size: i64) -> Self { pub fn empty(page: i64, page_size: i64) -> Self {
Pageable { Pageable {
data: vec![], data: vec![],
@ -34,4 +30,4 @@ where
page_size, page_size,
} }
} }
} }

View File

@ -10,34 +10,16 @@ use syn::{Data, DeriveInput, Fields}; // 用于解析宏输入
pub fn gen_responsable(input: DeriveInput) -> TokenStream { pub fn gen_responsable(input: DeriveInput) -> TokenStream {
let name = &input.ident; // 获取结构体名称 let name = &input.ident; // 获取结构体名称
let generics = &input.generics; // 获取泛型参数
let (impl_generics, _ty_generics, where_clause) = generics.split_for_impl();
let gen = match input.data { let gen = match input.data {
Data::Struct(ref data) => match data.fields { Data::Struct(ref data) => match data.fields {
Fields::Named(ref _fields) => { Fields::Named(ref _fields) => {
// // 处理命名字段 // 处理命名字段
// let field_names = fields.named.iter().map(|f| &f.ident); // 获取所有字段名称
// let field_types = fields.named.iter().map(|f| &f.ty); // 获取所有字段类型
// // 获取`status`属性
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
// Some(attr) => {
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
// quote! { #status_lit } // 生成状态码
// },
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
// };
// // 获取`headers`属性
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
// Some(attr) => {
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
// quote! { #headers_lit } // 生成头部信息
// },
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
// };
// 生成实现`IntoResponse` trait的代码 // 生成实现`IntoResponse` trait的代码
quote! { quote! {
impl axum::response::IntoResponse for #name { impl #impl_generics axum::response::IntoResponse for #name #generics #where_clause {
fn into_response(self) -> axum::http::Response<axum::body::Body> { fn into_response(self) -> axum::http::Response<axum::body::Body> {
let mut builder = hyper::Response::builder(); let mut builder = hyper::Response::builder();
// .status(#status) // 设置状态码 // .status(#status) // 设置状态码
@ -51,31 +33,11 @@ pub fn gen_responsable(input: DeriveInput) -> TokenStream {
} }
}, },
Fields::Unnamed(ref _fields) => { Fields::Unnamed(ref _fields) => {
// // 处理未命名字段 // 处理未命名字段
// let field_names = fields.unnamed.iter().enumerate().map(|(i, _)| i); // 获取所有字段索引
// let field_types = fields.unnamed.iter().map(|f| &f.ty); // 获取所有字段类型
// // 获取`status`属性
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
// Some(attr) => {
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
// quote! { #status_lit } // 生成状态码
// },
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
// };
// // 获取`headers`属性
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
// Some(attr) => {
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
// quote! { #headers_lit } // 生成头部信息
// },
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
// };
// 生成实现`IntoResponse` trait的代码 // 生成实现`IntoResponse` trait的代码
quote! { quote! {
impl axum::response::IntoResponse for #name { impl #impl_generics axum::response::IntoResponse for #name #generics #where_clause {
fn into_response(self) -> axum::http::Response<axum::body::Body> { fn into_response(self) -> axum::http::Response<axum::body::Body> {
// let mut builder = hyper::Response::builder(); // let mut builder = hyper::Response::builder();
// .status(#status) // 设置状态码 // .status(#status) // 设置状态码
@ -89,28 +51,11 @@ pub fn gen_responsable(input: DeriveInput) -> TokenStream {
} }
}, },
Fields::Unit => { Fields::Unit => {
// // 处理无字段的结构体 // 处理无字段的结构体
// // 获取`status`属性
// let status = match input.attrs.iter().find(|attr| attr.path().is_ident("status")) {
// Some(attr) => {
// let status_lit = attr.parse_args::<Ident>().unwrap(); // 解析`status`属性值
// quote! { #status_lit } // 生成状态码
// },
// None => quote! { hyper::StatusCode::OK }, // 默认状态码为`OK`
// };
// // 获取`headers`属性
// let headers = match input.attrs.iter().find(|attr| attr.path().is_ident("headers")) {
// Some(attr) => {
// let headers_lit = attr.parse_args::<Ident>().unwrap(); // 解析`headers`属性值
// quote! { #headers_lit } // 生成头部信息
// },
// None => quote! { hyper::HeaderMap::new() }, // 默认头部信息为空
// };
// 生成实现`IntoResponse` trait的代码 // 生成实现`IntoResponse` trait的代码
quote! { quote! {
impl axum::response::IntoResponse for #name { impl #impl_generics axum::response::IntoResponse for #name #generics #where_clause {
fn into_response(self) -> axum::http::Response<axum::body::Body> { fn into_response(self) -> axum::http::Response<axum::body::Body> {
// let mut builder = hyper::Response::builder(); // let mut builder = hyper::Response::builder();
// .status(#status) // 设置状态码 // .status(#status) // 设置状态码

View File

@ -1,8 +1,8 @@
extern crate macros; extern crate macros;
use domain::dto::feedback::FeedbackAdd; use domain::entities::feedback::Feedback;
use domain::{dto::feedback::FeedbackAdd, vo::pageable::Pageable};
use domain::dto::pageable::PageParams; use domain::dto::pageable::PageParams;
use domain::vo::feedback::FeedbackPageable;
use library::context::Context; use library::context::Context;
use library::extractor::path_extractor::PathVar; use library::extractor::path_extractor::PathVar;
use library::model::response::ResResult; use library::model::response::ResResult;
@ -26,7 +26,7 @@ pub async fn add_feedback(
pub async fn get_feedback_list_by_page( pub async fn get_feedback_list_by_page(
context: Context, context: Context,
QueryParams(page_params): QueryParams<PageParams>, QueryParams(page_params): QueryParams<PageParams>,
) -> ResResult<FeedbackPageable> { ) -> ResResult<Pageable<Feedback>> {
service::feedback_service::get_feedback_list_by_page( service::feedback_service::get_feedback_list_by_page(
context, context,
page_params.page.unwrap(), page_params.page.unwrap(),
@ -39,7 +39,7 @@ pub async fn get_feedback_list_by_page(
pub async fn get_feedback_list( pub async fn get_feedback_list(
context: Context, context: Context,
PathVar(page_params): PathVar<PageParams>, PathVar(page_params): PathVar<PageParams>,
) -> ResResult<FeedbackPageable> { ) -> ResResult<Pageable<Feedback>> {
service::feedback_service::get_feedback_list_by_page( service::feedback_service::get_feedback_list_by_page(
context, context,
page_params.page.unwrap(), page_params.page.unwrap(),

View File

@ -1,6 +1,6 @@
use domain::dto::feedback::FeedbackAdd; use domain::dto::feedback::FeedbackAdd;
use domain::entities::feedback::Feedback; use domain::entities::feedback::Feedback;
use domain::vo::feedback::FeedbackPageable; use domain::vo::pageable::Pageable;
use library::context::Context; use library::context::Context;
use library::db; use library::db;
use library::model::response::ResResult; use library::model::response::ResResult;
@ -10,18 +10,18 @@ pub async fn get_feedback_list_by_page(
context: Context, context: Context,
page: i64, page: i64,
page_size: i64, page_size: i64,
) -> ResResult<FeedbackPageable> { ) -> ResResult<Pageable<Feedback>> {
if !context.account.unwrap().role.is_admin() { if !context.account.unwrap().role.is_admin() {
tracing::error!("非管理员用户,无法获取反馈信息列表"); tracing::error!("非管理员用户,无法获取反馈信息列表");
return Ok(FeedbackPageable::empty(page, page_size)); return Ok(Pageable::<Feedback>::empty(page, page_size));
} }
let feedback_list = Feedback::search_feedback(page, page_size, db!()).await.ok(); let feedback_list = Feedback::search_feedback(page, page_size, db!()).await.ok();
if feedback_list.is_none() { if feedback_list.is_none() {
tracing::error!("反馈信息为空"); tracing::error!("反馈信息为空");
return Ok(FeedbackPageable::empty(page, page_size)); return Ok(Pageable::<Feedback>::empty(page, page_size));
} }
let total = get_feedback_count().await; let total = get_feedback_count().await;
Ok(FeedbackPageable::new( Ok(Pageable::<Feedback>::new(
feedback_list.unwrap(), feedback_list.unwrap(),
total, total,
page, page,