添加草稿电子地图数据创建,查询相关接口
All checks were successful
build / build-rust (push) Successful in 2m8s

This commit is contained in:
soul-walker 2024-11-13 14:39:19 +08:00
parent 8791aee96c
commit 7a64171b96
9 changed files with 188 additions and 22 deletions

View File

@ -62,8 +62,10 @@ mod tests {
#[test] #[test]
fn test_md5() { fn test_md5() {
let input = "hello"; // let input = "hello";
let input = "joylink0503";
let output = md5(input); let output = md5(input);
assert_eq!(output, "5d41402abc4b2a76b9719d911017c592"); println!("{}", output);
// assert_eq!(output, "5d41402abc4b2a76b9719d911017c592");
} }
} }

View File

@ -29,6 +29,10 @@ fn main() {
"common.DataType", "common.DataType",
"#[derive(sqlx::Type, async_graphql::Enum, serde::Serialize, serde::Deserialize)]", "#[derive(sqlx::Type, async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
) )
.type_attribute(
"common.LineType",
"#[derive(async_graphql::Enum, serde::Serialize, serde::Deserialize)]",
)
.type_attribute( .type_attribute(
"common.IscsStyle", "common.IscsStyle",
"#[derive(async_graphql::Enum, serde::Serialize, serde::Deserialize)]", "#[derive(async_graphql::Enum, serde::Serialize, serde::Deserialize)]",

View File

@ -199,6 +199,56 @@ impl DataType {
} }
} }
} }
/// 线路类型
#[derive(
async_graphql::Enum,
serde::Serialize,
serde::Deserialize,
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
::prost::Enumeration,
)]
#[repr(i32)]
pub enum LineType {
/// 未知
Unknown = 0,
/// 城市轨道交通
Ur = 1,
/// 城际轨道交通
Ir = 2,
/// 市域轨道交通
Cr = 3,
}
impl LineType {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
LineType::Unknown => "LineType_Unknown",
LineType::Ur => "LineType_Ur",
LineType::Ir => "LineType_Ir",
LineType::Cr => "LineType_Cr",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"LineType_Unknown" => Some(Self::Unknown),
"LineType_Ur" => Some(Self::Ur),
"LineType_Ir" => Some(Self::Ir),
"LineType_Cr" => Some(Self::Cr),
_ => None,
}
}
}
#[derive( #[derive(
async_graphql::Enum, async_graphql::Enum,
serde::Serialize, serde::Serialize,

View File

@ -1,16 +1,28 @@
use async_graphql::{InputObject, InputType, OutputType, SimpleObject}; use async_graphql::{InputObject, InputType, OutputType, SimpleObject};
use rtsa_db::{common::TableColumn, model::DraftDataColumn}; use rtsa_db::{common::TableColumn, model::DraftDataColumn};
use rtsa_dto::common::IscsStyle; use rtsa_dto::common::{IscsStyle, LineType};
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value;
pub trait DataOptions: InputType + OutputType + Serialize + DeserializeOwned { pub trait DataOptions: InputType + OutputType + Serialize + DeserializeOwned {
fn to_data_options_filter_clause(&self) -> String; fn to_data_options_filter_clause(&self) -> String;
} }
impl DataOptions for Value { // impl DataOptions for Value {
// fn to_data_options_filter_clause(&self) -> String {
// format!("{} @> '{}'", DraftDataColumn::Options.name(), self)
// }
// }
impl<T> DataOptions for T
where
T: ?Sized + Serialize + DeserializeOwned + OutputType + InputType,
{
fn to_data_options_filter_clause(&self) -> String { fn to_data_options_filter_clause(&self) -> String {
format!("{} @> '{}'", DraftDataColumn::Options.name(), self) format!(
"{} @> '{}'",
DraftDataColumn::Options.name(),
serde_json::to_string(self).unwrap()
)
} }
} }
@ -20,14 +32,14 @@ pub struct IscsDataOptions {
pub style: IscsStyle, pub style: IscsStyle,
} }
impl DataOptions for IscsDataOptions { #[derive(Debug, Clone, InputObject, SimpleObject, Serialize, Deserialize)]
fn to_data_options_filter_clause(&self) -> String { #[graphql(input_name = "LineInfoOptionsInput")]
let options_column = DraftDataColumn::Options.name(); pub struct LineInfoOptions {
format!( pub line_type: LineType,
"{options_column} @> '{}'", /// 城轨线路所属城市
serde_json::to_string(self).unwrap() pub city: Option<String>,
) /// 城轨线路编号
} pub line_code: Option<String>,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -11,7 +11,7 @@ use serde_json::Value;
use crate::apis::{PageDto, PageQueryDto}; use crate::apis::{PageDto, PageQueryDto};
use crate::loader::RtsaDbLoader; use crate::loader::RtsaDbLoader;
use super::data_options_def::{DataOptions, IscsDataOptions}; use super::data_options_def::{DataOptions, IscsDataOptions, LineInfoOptions};
use super::release_data::ReleaseDataId; use super::release_data::ReleaseDataId;
use super::user::UserId; use super::user::UserId;
@ -39,6 +39,37 @@ impl DraftDataQuery {
.await?; .await?;
Ok(paging_result.into()) Ok(paging_result.into())
} }
/// 分页查询用户电子地图草稿数据
#[graphql(guard = "RoleGuard::new(Role::User)")]
async fn user_draft_em_data_paging<'ctx>(
&self,
ctx: &Context<'ctx>,
paging: PageQueryDto,
mut query: UserDraftDataFilterDto<LineInfoOptions>,
) -> async_graphql::Result<PageDto<DraftEmDataDto>> {
let claims = ctx.data::<Jwt>()?.decode()?;
query = query.with_data_type_and_user_id(DataType::Em, claims.uid);
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
let paging_result = db_accessor
.paging_query_draft_data(query.into(), paging.into())
.await?;
Ok(paging_result.into())
}
/// 分页查询共享的草稿电子地图数据
#[graphql(guard = "RoleGuard::new(Role::User)")]
async fn shared_draft_em_data_paging<'ctx>(
&self,
ctx: &Context<'ctx>,
paging: PageQueryDto,
mut query: DraftDataFilterDto<LineInfoOptions>,
) -> async_graphql::Result<PageDto<DraftEmDataDto>> {
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
query.data_type = Some(DataType::Em);
let paging_result = db_accessor
.paging_query_draft_data(query.into(), paging.into())
.await?;
Ok(paging_result.into())
}
/// 分页查询用户的草稿ISCS数据 /// 分页查询用户的草稿ISCS数据
#[graphql(guard = "RoleGuard::new(Role::User)")] #[graphql(guard = "RoleGuard::new(Role::User)")]
async fn user_draft_iscs_data_paging<'ctx>( async fn user_draft_iscs_data_paging<'ctx>(
@ -48,8 +79,7 @@ impl DraftDataQuery {
mut query: UserDraftDataFilterDto<IscsDataOptions>, mut query: UserDraftDataFilterDto<IscsDataOptions>,
) -> async_graphql::Result<PageDto<DraftIscsDataDto>> { ) -> async_graphql::Result<PageDto<DraftIscsDataDto>> {
let claims = ctx.data::<Jwt>()?.decode()?; let claims = ctx.data::<Jwt>()?.decode()?;
query.user_id = claims.uid; query = query.with_data_type_and_user_id(DataType::Iscs, claims.uid);
query.data_type = Some(DataType::Iscs);
let db_accessor = ctx.data::<RtsaDbAccessor>()?; let db_accessor = ctx.data::<RtsaDbAccessor>()?;
let paging_result = db_accessor let paging_result = db_accessor
.paging_query_draft_data(query.into(), paging.into()) .paging_query_draft_data(query.into(), paging.into())
@ -98,6 +128,20 @@ impl DraftDataQuery {
#[Object] #[Object]
impl DraftDataMutation { impl DraftDataMutation {
/// 创建电子地图草稿数据
#[graphql(guard = "RoleGuard::new(Role::User)")]
async fn create_draft_em_data(
&self,
ctx: &Context<'_>,
mut input: CreateDraftDataDto<LineInfoOptions>,
) -> async_graphql::Result<DraftDataDto> {
let claims = ctx.data::<Jwt>()?.decode()?;
input = input.with_data_type_and_user_id(DataType::Em, claims.uid);
let db_accessor = ctx.data::<RtsaDbAccessor>()?;
let draft_data = db_accessor.create_draft_data(input.into()).await?;
Ok(draft_data.into())
}
/// 创建草稿ISCS数据 /// 创建草稿ISCS数据
#[graphql(guard = "RoleGuard::new(Role::User)")] #[graphql(guard = "RoleGuard::new(Role::User)")]
async fn create_draft_iscs_data( async fn create_draft_iscs_data(
@ -194,6 +238,7 @@ impl DraftDataMutation {
#[derive(Debug, InputObject)] #[derive(Debug, InputObject)]
#[graphql(concrete(name = "CreateDraftIscsDto", params(IscsDataOptions)))] #[graphql(concrete(name = "CreateDraftIscsDto", params(IscsDataOptions)))]
#[graphql(concrete(name = "CreateDraftEmDto", params(LineInfoOptions)))]
pub struct CreateDraftDataDto<T: DataOptions> { pub struct CreateDraftDataDto<T: DataOptions> {
#[graphql(skip)] #[graphql(skip)]
pub data_type: Option<DataType>, pub data_type: Option<DataType>,
@ -228,6 +273,7 @@ impl<T: DataOptions> From<CreateDraftDataDto<T>> for rtsa_db::CreateDraftData {
/// 用户的草稿数据查询条件 /// 用户的草稿数据查询条件
#[derive(Debug, InputObject)] #[derive(Debug, InputObject)]
#[graphql(concrete(name = "UserDraftEmDataFilterDto", params(LineInfoOptions)))]
#[graphql(concrete(name = "UserDraftIscsDataFilterDto", params(IscsDataOptions)))] #[graphql(concrete(name = "UserDraftIscsDataFilterDto", params(IscsDataOptions)))]
pub struct UserDraftDataFilterDto<T: DataOptions> { pub struct UserDraftDataFilterDto<T: DataOptions> {
#[graphql(skip)] #[graphql(skip)]
@ -239,6 +285,14 @@ pub struct UserDraftDataFilterDto<T: DataOptions> {
pub is_shared: Option<bool>, pub is_shared: Option<bool>,
} }
impl<T: DataOptions> UserDraftDataFilterDto<T> {
pub fn with_data_type_and_user_id(mut self, data_type: DataType, id: i32) -> Self {
self.data_type = Some(data_type);
self.user_id = id;
self
}
}
impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtsa_db::DraftDataQuery { impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtsa_db::DraftDataQuery {
fn from(value: UserDraftDataFilterDto<T>) -> Self { fn from(value: UserDraftDataFilterDto<T>) -> Self {
Self { Self {
@ -254,6 +308,7 @@ impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtsa_db::DraftDataQuery
/// 共享的草稿数据查询条件 /// 共享的草稿数据查询条件
#[derive(Debug, InputObject)] #[derive(Debug, InputObject)]
#[graphql(concrete(name = "DraftDataFilterDto", params(Value)))] #[graphql(concrete(name = "DraftDataFilterDto", params(Value)))]
#[graphql(concrete(name = "SharedDraftEmDataFilterDto", params(LineInfoOptions)))]
#[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))] #[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))]
pub struct DraftDataFilterDto<T: DataOptions> { pub struct DraftDataFilterDto<T: DataOptions> {
@ -336,6 +391,26 @@ impl From<rtsa_db::model::DraftDataModel> for DraftDataDto {
} }
} }
/// 草稿电子地图数据
#[derive(Debug, SimpleObject)]
pub struct DraftEmDataDto {
pub draft_data: DraftDataDto,
pub options: Option<LineInfoOptions>,
}
impl From<rtsa_db::model::DraftDataModel> for DraftEmDataDto {
fn from(value: rtsa_db::model::DraftDataModel) -> Self {
Self {
options: value
.options
.clone()
.map(|o| serde_json::from_value(o).unwrap()),
draft_data: value.into(),
}
}
}
/// ISCS草稿数据
#[derive(Debug, SimpleObject)] #[derive(Debug, SimpleObject)]
pub struct DraftIscsDataDto { pub struct DraftIscsDataDto {
pub draft_data: DraftDataDto, pub draft_data: DraftDataDto,

View File

@ -67,6 +67,7 @@ impl From<PageQueryDto> for rtsa_db::common::PageQuery {
#[derive(Debug, SimpleObject)] #[derive(Debug, SimpleObject)]
#[graphql(concrete(name = "UserPageDto", params(user::UserDto)))] #[graphql(concrete(name = "UserPageDto", params(user::UserDto)))]
#[graphql(concrete(name = "DraftDataPageDto", params(draft_data::DraftDataDto)))] #[graphql(concrete(name = "DraftDataPageDto", params(draft_data::DraftDataDto)))]
#[graphql(concrete(name = "DraftEmDataPageDto", params(draft_data::DraftEmDataDto)))]
#[graphql(concrete(name = "DraftIscsDataPageDto", params(draft_data::DraftIscsDataDto)))] #[graphql(concrete(name = "DraftIscsDataPageDto", params(draft_data::DraftIscsDataDto)))]
#[graphql(concrete(name = "ReleaseDataPageDto", params(release_data::ReleaseDataDto)))] #[graphql(concrete(name = "ReleaseDataPageDto", params(release_data::ReleaseDataDto)))]
#[graphql(concrete( #[graphql(concrete(

View File

@ -72,6 +72,13 @@ mod tests {
assert_eq!(org.name, DEFAULT_ORG_NAME); assert_eq!(org.name, DEFAULT_ORG_NAME);
assert_eq!(org.creator_id, user.id); assert_eq!(org.creator_id, user.id);
let user = db_accessor
.query_user_login(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.await?;
assert_eq!(user.username, ADMIN_USER_NAME);
assert_eq!(user.nickname, ADMIN_USER_NAME);
assert_eq!(user.roles, json!([Role::Admin]));
Ok(()) Ok(())
} }
} }

View File

@ -1,7 +1,7 @@
use async_graphql::Guard; use async_graphql::Guard;
use rtsa_db::prelude::*; use rtsa_db::prelude::*;
use rtsa_dto::common::Role; use rtsa_dto::common::Role;
use rtsa_log::tracing::{info, warn}; use rtsa_log::tracing::{error, info, warn};
use serde_json::json; use serde_json::json;
mod jwt_auth; mod jwt_auth;
@ -113,9 +113,24 @@ pub(crate) async fn handle_login(
)) ))
} }
} }
_ => Err(BusinessError::AuthError( DbAccessError::PasswordNotMatch => {
"用户不存在或密码不正确".to_string(), warn!(
)), "密码不匹配: username={}, password={}, org_id={}",
user_login_dto.username, user_login_dto.password, org_id
);
Err(BusinessError::AuthError(
"用户不存在或密码不正确".to_string(),
))
}
_ => {
error!(
"查询用户登录验证错误: username={}, org_id={}, error={:?}",
user_login_dto.username, org_id, e
);
Err(BusinessError::AuthError(
"用户不存在或密码不正确".to_string(),
))
}
} }
} }
} }

@ -1 +1 @@
Subproject commit 867c075833ffbe64b0291db921adddc9d5d5a7a3 Subproject commit a30bf52339620075e8d666be363eb3d93d532656