调整接口结构
All checks were successful
build / build-rust (push) Successful in 2m26s

添加发布数据的几个接口
删除发布数据版本表的版本字段
This commit is contained in:
soul-walker 2024-09-19 21:25:52 +08:00
parent b64200284a
commit ed45a08ad7
11 changed files with 413 additions and 191 deletions

View File

@ -0,0 +1,53 @@
use async_graphql::{InputObject, InputType, OutputType, SimpleObject};
use rtss_db::{common::TableColumn, model::DraftDataColumn};
use rtss_dto::common::IscsStyle;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
pub trait DataOptions: InputType + OutputType + Serialize + DeserializeOwned {
fn to_data_options_filter_clause(&self) -> String;
}
#[derive(Debug, InputObject, SimpleObject, Serialize, Deserialize)]
#[graphql(input_name = "IscsDataOptionsInput")]
pub struct IscsDataOptions {
pub style: IscsStyle,
}
impl DataOptions for IscsDataOptions {
fn to_data_options_filter_clause(&self) -> String {
let options_column = DraftDataColumn::Options.name();
format!(
"{options_column} @> '{}'",
serde_json::to_string(self).unwrap()
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_iscs_data_options_serialize() {
rtss_log::Logging::default().init();
let options = IscsDataOptions {
style: IscsStyle::DaShiZhiNeng,
};
let json = serde_json::to_string(&options).unwrap();
println!("{}", json);
println!("{}", options.style.as_str_name());
assert_eq!(json, r#"{"style":"DaShiZhiNeng"}"#);
let options: IscsDataOptions = serde_json::from_str(&json).unwrap();
assert_eq!(options.style, IscsStyle::DaShiZhiNeng);
}
#[test]
fn test_iscs_data_options_into_data_options_filter_clause() {
let options = IscsDataOptions {
style: IscsStyle::DaShiZhiNeng,
};
let clause = options.to_data_options_filter_clause();
println!("{clause}");
assert_eq!(clause, r#"options @> '{"style":"DaShiZhiNeng"}'"#);
}
}

View File

@ -1,16 +1,16 @@
use async_graphql::{Context, InputObject, Object, SimpleObject}; use async_graphql::{Context, InputObject, Object, SimpleObject};
use async_graphql::{InputType, OutputType}; use base64::prelude::*;
use base64::Engine;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use rtss_db::common::TableColumn;
use rtss_db::model::DraftDataColumn;
use rtss_db::DraftDataAccessor; use rtss_db::DraftDataAccessor;
use rtss_db::RtssDbAccessor; use rtss_db::RtssDbAccessor;
use rtss_dto::common::{DataType, IscsStyle}; use rtss_dto::common::DataType;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use crate::pagination::PageQueryDto; use crate::apis::PageQueryDto;
use super::common::{DataOptions, IscsDataOptions};
use super::PageDto;
#[derive(Default)] #[derive(Default)]
pub struct DraftDataQuery; pub struct DraftDataQuery;
@ -20,39 +20,39 @@ pub struct DraftDataMutation;
#[Object] #[Object]
impl DraftDataQuery { impl DraftDataQuery {
/// 分页查询全部草稿数据(系统管理用) /// 分页查询所有草稿数据(系统管理用)
async fn draft_data_paging<'ctx>( async fn draft_data_paging<'ctx>(
&self, &self,
ctx: &Context<'ctx>, ctx: &Context<'ctx>,
paging: PageQueryDto, paging: PageQueryDto,
query: DraftDataFilterDto, query: DraftDataFilterDto,
) -> async_graphql::Result<DraftDataPage> { ) -> async_graphql::Result<PageDto<DraftDataDto>> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging_result = db_accessor let paging_result = db_accessor
.query_draft_data(query.into(), paging.into()) .query_draft_data(query.into(), paging.into())
.await?; .await?;
Ok(paging_result.into()) Ok(paging_result.into())
} }
/// 分页查询用户的草稿数据 /// 分页查询用户的草稿ISCS数据
async fn user_draft_iscs_data_paging<'ctx>( async fn user_draft_iscs_data_paging<'ctx>(
&self, &self,
ctx: &Context<'ctx>, ctx: &Context<'ctx>,
paging: PageQueryDto, paging: PageQueryDto,
query: UserDraftDataFilterDto<IscsDataOptions>, query: UserDraftDataFilterDto<IscsDataOptions>,
) -> async_graphql::Result<DraftIscsDataPage> { ) -> async_graphql::Result<PageDto<DraftIscsDataDto>> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging_result = db_accessor let paging_result = db_accessor
.query_draft_data(query.into(), paging.into()) .query_draft_data(query.into(), paging.into())
.await?; .await?;
Ok(paging_result.into()) Ok(paging_result.into())
} }
/// 分页查询共享的草稿数据 /// 分页查询共享的草稿ISCS数据
async fn shared_draft_iscs_data_paging<'ctx>( async fn shared_draft_iscs_data_paging<'ctx>(
&self, &self,
ctx: &Context<'ctx>, ctx: &Context<'ctx>,
paging: PageQueryDto, paging: PageQueryDto,
query: SharedDraftDataFilterDto<IscsDataOptions>, query: SharedDraftDataFilterDto<IscsDataOptions>,
) -> async_graphql::Result<DraftIscsDataPage> { ) -> async_graphql::Result<PageDto<DraftIscsDataDto>> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging_result = db_accessor let paging_result = db_accessor
.query_draft_data(query.into(), paging.into()) .query_draft_data(query.into(), paging.into())
@ -60,11 +60,7 @@ impl DraftDataQuery {
Ok(paging_result.into()) Ok(paging_result.into())
} }
/// 根据id获取草稿数据 /// 根据id获取草稿数据
async fn draft_data( async fn draft_data(&self, ctx: &Context<'_>, id: i32) -> async_graphql::Result<DraftDataDto> {
&self,
ctx: &Context<'_>,
id: i32,
) -> async_graphql::Result<DraftDataWithStringOptions> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.query_draft_data_by_id(id).await?; let draft_data = db_accessor.query_draft_data_by_id(id).await?;
Ok(draft_data.into()) Ok(draft_data.into())
@ -89,7 +85,7 @@ impl DraftDataMutation {
&self, &self,
ctx: &Context<'_>, ctx: &Context<'_>,
input: CreateDraftDataDto<IscsDataOptions>, input: CreateDraftDataDto<IscsDataOptions>,
) -> async_graphql::Result<DraftData<IscsDataOptions>> { ) -> async_graphql::Result<DraftIscsDataDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.create_draft_data(input.into()).await?; let draft_data = db_accessor.create_draft_data(input.into()).await?;
Ok(draft_data.into()) Ok(draft_data.into())
@ -100,22 +96,22 @@ impl DraftDataMutation {
ctx: &Context<'_>, ctx: &Context<'_>,
id: i32, id: i32,
name: String, name: String,
) -> async_graphql::Result<DraftDataWithStringOptions> { ) -> async_graphql::Result<DraftDataDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.update_draft_data_name(id, &name).await?; let draft_data = db_accessor.update_draft_data_name(id, &name).await?;
Ok(draft_data.into()) Ok(draft_data.into())
} }
/// 更新草稿数据data /// 更新草稿数据data
/// data为base64编码的字符串
async fn update_draft_data_data( async fn update_draft_data_data(
&self, &self,
ctx: &Context<'_>, ctx: &Context<'_>,
id: i32, id: i32,
data: Vec<u8>, data: String, // base64编码的数据
) -> async_graphql::Result<DraftDataWithStringOptions> { ) -> async_graphql::Result<DraftDataDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor let bytes = BASE64_STANDARD.decode(data).expect("base64 decode error");
.update_draft_data_data(id, data.as_slice()) let draft_data = db_accessor.update_draft_data_data(id, &bytes).await?;
.await?;
Ok(draft_data.into()) Ok(draft_data.into())
} }
/// 更新草稿数据共享状态 /// 更新草稿数据共享状态
@ -124,7 +120,7 @@ impl DraftDataMutation {
ctx: &Context<'_>, ctx: &Context<'_>,
id: i32, id: i32,
is_shared: bool, is_shared: bool,
) -> async_graphql::Result<DraftDataWithStringOptions> { ) -> async_graphql::Result<DraftDataDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.set_draft_data_shared(id, is_shared).await?; let draft_data = db_accessor.set_draft_data_shared(id, is_shared).await?;
Ok(draft_data.into()) Ok(draft_data.into())
@ -145,7 +141,7 @@ impl DraftDataMutation {
ctx: &Context<'_>, ctx: &Context<'_>,
id: i32, id: i32,
release_data_id: i32, release_data_id: i32,
) -> async_graphql::Result<DraftDataWithStringOptions> { ) -> async_graphql::Result<DraftDataDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor let draft_data = db_accessor
.set_default_release_data_id(id, release_data_id) .set_default_release_data_id(id, release_data_id)
@ -159,7 +155,7 @@ impl DraftDataMutation {
id: i32, id: i32,
name: String, name: String,
user_id: i32, user_id: i32,
) -> async_graphql::Result<DraftDataWithStringOptions> { ) -> async_graphql::Result<DraftDataDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?; let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.save_as_new_draft(id, &name, user_id).await?; let draft_data = db_accessor.save_as_new_draft(id, &name, user_id).await?;
Ok(draft_data.into()) Ok(draft_data.into())
@ -208,27 +204,6 @@ impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtss_db::DraftDataQuery
} }
} }
pub trait DataOptions: InputType + OutputType + Serialize + DeserializeOwned {
fn to_data_options_filter_clause(&self) -> String;
}
#[derive(Debug, InputObject, SimpleObject, Serialize, Deserialize)]
#[graphql(input_name = "IscsDataOptionsInput")]
pub struct IscsDataOptions {
pub style: IscsStyle,
}
impl DataOptions for IscsDataOptions {
fn to_data_options_filter_clause(&self) -> String {
let options_column = DraftDataColumn::Options.name();
// format!("{options_column}['style'] = '\"{}\"'", self.style.as_str_name())
format!(
"{options_column} @> '{}'",
serde_json::to_string(self).unwrap()
)
}
}
/// 共享的草稿数据查询条件 /// 共享的草稿数据查询条件
#[derive(Debug, InputObject)] #[derive(Debug, InputObject)]
#[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))] #[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))]
@ -274,27 +249,32 @@ impl From<DraftDataFilterDto> for rtss_db::DraftDataQuery {
} }
#[derive(Debug, SimpleObject)] #[derive(Debug, SimpleObject)]
pub struct DraftDataWithStringOptions { pub struct DraftDataDto {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub data_type: rtss_dto::common::DataType, pub data_type: rtss_dto::common::DataType,
pub options: Option<Value>, pub options: Option<Value>,
pub data: Option<Vec<u8>>, /// base64编码的数据
pub data: Option<String>,
pub user_id: i32, pub user_id: i32,
pub default_release_data_id: Option<i32>,
pub is_shared: bool, pub is_shared: bool,
pub created_at: NaiveDateTime, pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime, pub updated_at: NaiveDateTime,
} }
impl From<rtss_db::model::DraftDataModel> for DraftDataWithStringOptions { impl From<rtss_db::model::DraftDataModel> for DraftDataDto {
fn from(value: rtss_db::model::DraftDataModel) -> Self { fn from(value: rtss_db::model::DraftDataModel) -> Self {
Self { Self {
id: value.id, id: value.id,
name: value.name, name: value.name,
data_type: DataType::try_from(value.data_type).unwrap(), data_type: DataType::try_from(value.data_type).unwrap(),
options: value.options, options: value.options,
data: value.data, data: value
.data
.map(|d| base64::prelude::BASE64_STANDARD.encode(d)),
user_id: value.user_id, user_id: value.user_id,
default_release_data_id: value.default_release_data_id,
is_shared: value.is_shared, is_shared: value.is_shared,
created_at: value.created_at.naive_local(), created_at: value.created_at.naive_local(),
updated_at: value.updated_at.naive_local(), updated_at: value.updated_at.naive_local(),
@ -303,90 +283,19 @@ impl From<rtss_db::model::DraftDataModel> for DraftDataWithStringOptions {
} }
#[derive(Debug, SimpleObject)] #[derive(Debug, SimpleObject)]
#[graphql(concrete(name = "DraftIscsData", params(IscsDataOptions)))] pub struct DraftIscsDataDto {
pub struct DraftData<T: OutputType> { pub draft_data: DraftDataDto,
pub id: i32, pub options: Option<IscsDataOptions>,
pub name: String,
pub data_type: rtss_dto::common::DataType,
pub options: Option<T>,
pub data: Option<Vec<u8>>,
pub user_id: i32,
pub is_shared: bool,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
} }
impl<T: DataOptions> From<rtss_db::model::DraftDataModel> for DraftData<T> { impl From<rtss_db::model::DraftDataModel> for DraftIscsDataDto {
fn from(value: rtss_db::model::DraftDataModel) -> Self { fn from(value: rtss_db::model::DraftDataModel) -> Self {
Self { Self {
id: value.id, options: value
name: value.name, .options
data_type: DataType::try_from(value.data_type).unwrap(), .clone()
options: value.options.map(|o| serde_json::from_value(o).unwrap()), .map(|o| serde_json::from_value(o).unwrap()),
data: value.data, draft_data: value.into(),
user_id: value.user_id,
is_shared: value.is_shared,
created_at: value.created_at.naive_local(),
updated_at: value.updated_at.naive_local(),
} }
} }
} }
#[derive(Debug, SimpleObject)]
pub struct DraftDataPage {
pub total: i64,
pub data: Vec<DraftDataWithStringOptions>,
}
impl From<rtss_db::common::PageResult<rtss_db::model::DraftDataModel>> for DraftDataPage {
fn from(value: rtss_db::common::PageResult<rtss_db::model::DraftDataModel>) -> Self {
Self {
total: value.total,
data: value.data.into_iter().map(|m| m.into()).collect(),
}
}
}
#[derive(Debug, SimpleObject)]
pub struct DraftIscsDataPage {
pub total: i64,
pub data: Vec<DraftData<IscsDataOptions>>,
}
impl From<rtss_db::common::PageResult<rtss_db::model::DraftDataModel>> for DraftIscsDataPage {
fn from(value: rtss_db::common::PageResult<rtss_db::model::DraftDataModel>) -> Self {
Self {
total: value.total,
data: value.data.into_iter().map(|m| m.into()).collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_iscs_data_options_serialize() {
rtss_log::Logging::default().init();
let options = IscsDataOptions {
style: IscsStyle::DaShiZhiNeng,
};
let json = serde_json::to_string(&options).unwrap();
println!("{}", json);
println!("{}", options.style.as_str_name());
assert_eq!(json, r#"{"style":"DaShiZhiNeng"}"#);
let options: IscsDataOptions = serde_json::from_str(&json).unwrap();
assert_eq!(options.style, IscsStyle::DaShiZhiNeng);
}
#[test]
fn test_iscs_data_options_into_data_options_filter_clause() {
let options = IscsDataOptions {
style: IscsStyle::DaShiZhiNeng,
};
let clause = options.to_data_options_filter_clause();
println!("{clause}");
assert_eq!(clause, r#"options @> '{"style":"DaShiZhiNeng"}'"#);
}
}

View File

@ -0,0 +1,68 @@
use async_graphql::MergedObject;
use async_graphql::{Enum, InputObject, OutputType, SimpleObject};
use draft_data::{DraftDataMutation, DraftDataQuery};
use release_data::{ReleaseDataMutation, ReleaseDataQuery};
mod common;
mod draft_data;
mod release_data;
mod simulation;
#[derive(Default, MergedObject)]
pub struct Query(DraftDataQuery, ReleaseDataQuery);
#[derive(Default, MergedObject)]
pub struct Mutation(DraftDataMutation, ReleaseDataMutation);
#[derive(Enum, Copy, Clone, Default, Eq, PartialEq, Debug)]
#[graphql(remote = "rtss_db::common::SortOrder")]
pub enum SortOrder {
#[default]
Asc,
Desc,
}
#[derive(InputObject, Debug)]
pub struct PageQueryDto {
#[graphql(default = 1)]
pub page: i32,
#[graphql(default = 10)]
pub items_per_page: i32,
}
impl From<PageQueryDto> for rtss_db::common::PageQuery {
fn from(value: PageQueryDto) -> Self {
Self {
page: value.page,
items_per_page: value.items_per_page,
}
}
}
#[derive(Debug, SimpleObject)]
#[graphql(concrete(name = "DraftDataPageDto", params(draft_data::DraftDataDto)))]
#[graphql(concrete(name = "DraftIscsDataPageDto", params(draft_data::DraftIscsDataDto)))]
#[graphql(concrete(name = "ReleaseDataPageDto", params(release_data::ReleaseDataDto)))]
#[graphql(concrete(
name = "ReleaseIscsDataPageDto",
params(release_data::ReleaseIscsDataWithoutVersionDto)
))]
pub struct PageDto<T: OutputType> {
pub total: i64,
pub items: Vec<T>,
}
impl<T: OutputType> PageDto<T> {
pub fn new(total: i64, items: Vec<T>) -> Self {
Self { total, items }
}
}
impl<T: OutputType, M: Into<T>> From<rtss_db::common::PageResult<M>> for PageDto<T> {
fn from(value: rtss_db::common::PageResult<M>) -> Self {
Self::new(
value.total,
value.data.into_iter().map(|m| m.into()).collect(),
)
}
}

View File

@ -0,0 +1,214 @@
use async_graphql::{Context, InputObject, Object, SimpleObject};
use base64::prelude::*;
use chrono::NaiveDateTime;
use rtss_db::model::*;
use rtss_db::{model::ReleaseDataModel, ReleaseDataAccessor, RtssDbAccessor};
use rtss_dto::common::DataType;
use serde_json::Value;
use super::common::IscsDataOptions;
use super::{PageDto, PageQueryDto};
#[derive(Default)]
pub struct ReleaseDataQuery;
#[derive(Default)]
pub struct ReleaseDataMutation;
#[Object]
impl ReleaseDataQuery {
/// 分页查询所有发布数据(系统管理用)
async fn release_data_paging(
&self,
ctx: &Context<'_>,
page: PageQueryDto,
query: ReleaseDataFilterDto,
) -> async_graphql::Result<PageDto<ReleaseDataDto>> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging = db_accessor
.query_release_data_list(query.into(), page.into())
.await?;
Ok(paging.into())
}
/// 分页查询用户发布的ISCS数据
async fn user_release_iscs_data_paging(
&self,
ctx: &Context<'_>,
page: PageQueryDto,
query: UserReleaseDataFilterDto,
) -> async_graphql::Result<PageDto<ReleaseIscsDataWithoutVersionDto>> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging = db_accessor
.query_release_data_list(query.into(), page.into())
.await?;
Ok(paging.into())
}
/// id查询发布数据
async fn release_data(
&self,
ctx: &Context<'_>,
id: i32,
) -> async_graphql::Result<ReleaseDataWithUsedVersionDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let model = db_accessor.query_release_data_with_used_version(id).await?;
Ok(model.into())
}
}
#[Object]
impl ReleaseDataMutation {
/// 发布到新的发布数据
async fn release_new_from_draft(
&self,
ctx: &Context<'_>,
draft_id: i32,
name: String,
description: String,
) -> async_graphql::Result<ReleaseDataWithUsedVersionDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let result = db_accessor
.release_new_from_draft(draft_id, &name, &description)
.await?;
Ok(result.into())
}
/// 发布到默认发布数据需要草稿数据发布过或设置了默认发布数据id
async fn release_to_default_release_data(
&self,
ctx: &Context<'_>,
draft_id: i32,
description: String,
) -> async_graphql::Result<ReleaseDataWithUsedVersionDto> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let result = db_accessor
.release_to_existing(draft_id, &description)
.await?;
Ok(result.into())
}
}
#[derive(Debug, InputObject)]
pub struct ReleaseDataFilterDto {
pub name: Option<String>,
pub user_id: Option<i32>,
pub data_type: Option<DataType>,
pub is_published: Option<bool>,
}
#[derive(Debug, InputObject)]
pub struct UserReleaseDataFilterDto {
pub user_id: i32,
pub name: Option<String>,
pub data_type: Option<DataType>,
pub is_published: Option<bool>,
}
impl From<UserReleaseDataFilterDto> for rtss_db::ReleaseDataQuery {
fn from(value: UserReleaseDataFilterDto) -> Self {
Self {
name: value.name,
user_id: Some(value.user_id),
data_type: value.data_type,
is_published: value.is_published,
}
}
}
impl From<ReleaseDataFilterDto> for rtss_db::ReleaseDataQuery {
fn from(value: ReleaseDataFilterDto) -> Self {
Self {
name: value.name,
user_id: value.user_id,
data_type: value.data_type,
is_published: value.is_published,
}
}
}
#[derive(Debug, SimpleObject)]
pub struct ReleaseDataDto {
pub id: i32,
pub name: String,
pub data_type: String,
pub options: Option<Value>,
pub used_version_id: Option<i32>,
pub user_id: i32,
pub is_published: bool,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
}
#[derive(Debug, SimpleObject)]
pub struct ReleaseIscsDataWithoutVersionDto {
pub release_data: ReleaseDataDto,
pub options: Option<IscsDataOptions>,
}
impl From<ReleaseDataModel> for ReleaseIscsDataWithoutVersionDto {
fn from(model: ReleaseDataModel) -> Self {
Self {
options: model
.options
.clone()
.map(|o| serde_json::from_value(o).unwrap()),
release_data: model.into(),
}
}
}
#[derive(Debug, SimpleObject)]
pub struct ReleaseDataWithUsedVersionDto {
pub release_data: ReleaseDataDto,
pub used_version: Option<ReleaseDataVersionDto>,
}
#[derive(Debug, SimpleObject)]
pub struct ReleaseDataVersionDto {
pub id: i32,
pub release_data_id: i32,
pub description: String,
/// base64编码的数据
pub data: String,
pub user_id: i32,
pub created_at: NaiveDateTime,
}
impl From<(ReleaseDataModel, ReleaseDataVersionModel)> for ReleaseDataWithUsedVersionDto {
fn from((data, version): (ReleaseDataModel, ReleaseDataVersionModel)) -> Self {
Self {
release_data: data.into(),
used_version: Some(version.into()),
}
}
}
impl From<ReleaseDataVersionModel> for ReleaseDataVersionDto {
fn from(model: ReleaseDataVersionModel) -> Self {
Self {
id: model.id,
release_data_id: model.release_data_id,
description: model.description,
data: BASE64_STANDARD.encode(model.data),
user_id: model.user_id,
created_at: model.created_at.naive_local(),
}
}
}
impl From<ReleaseDataModel> for ReleaseDataDto {
fn from(model: ReleaseDataModel) -> Self {
Self {
id: model.id,
name: model.name,
data_type: model.data_type.to_string(),
options: model.options,
used_version_id: model.used_version_id,
user_id: model.user_id,
is_published: model.is_published,
created_at: model.created_at.naive_local(),
updated_at: model.updated_at.naive_local(),
}
}
}

View File

@ -1,8 +1,6 @@
mod draft_data;
// mod jwt_auth; // mod jwt_auth;
mod pagination; mod apis;
mod server; mod server;
mod simulation;
mod simulation_definition; mod simulation_definition;
mod sys_info; mod sys_info;

View File

@ -1,29 +0,0 @@
use async_graphql::{Enum, InputObject, SimpleObject};
#[derive(Enum, Copy, Clone, Default, Eq, PartialEq, Debug)]
#[graphql(remote = "rtss_db::common::SortOrder")]
pub enum SortOrder {
#[default]
Asc,
Desc,
}
#[derive(InputObject, Debug)]
pub struct PageQueryDto {
pub page: i32,
pub items_per_page: i32,
}
impl From<PageQueryDto> for rtss_db::common::PageQuery {
fn from(value: PageQueryDto) -> Self {
Self {
page: value.page,
items_per_page: value.items_per_page,
}
}
}
#[derive(SimpleObject)]
pub struct PageDto {
pub total: i64,
}

View File

@ -14,7 +14,7 @@ use rtss_log::tracing::{debug, info};
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tower_http::cors::CorsLayer; use tower_http::cors::CorsLayer;
use crate::draft_data; use crate::apis::{Mutation, Query};
use crate::simulation_definition::MutexSimulationManager; use crate::simulation_definition::MutexSimulationManager;
pub struct ServerConfig { pub struct ServerConfig {
@ -83,12 +83,6 @@ async fn graphiql() -> impl IntoResponse {
pub type SimulationSchema = Schema<Query, Mutation, EmptySubscription>; pub type SimulationSchema = Schema<Query, Mutation, EmptySubscription>;
#[derive(Default, MergedObject)]
pub struct Query(draft_data::DraftDataQuery);
#[derive(Default, MergedObject)]
pub struct Mutation(draft_data::DraftDataMutation);
pub async fn new_schema(config: &ServerConfig) -> SimulationSchema { pub async fn new_schema(config: &ServerConfig) -> SimulationSchema {
let dba = rtss_db::get_db_accessor(&config.database_url).await; let dba = rtss_db::get_db_accessor(&config.database_url).await;
Schema::build(Query::default(), Mutation::default(), EmptySubscription) Schema::build(Query::default(), Mutation::default(), EmptySubscription)

View File

@ -175,16 +175,19 @@ impl ReleaseDataAccessor for RtssDbAccessor {
// 创建发布数据 // 创建发布数据
let rd_table = ReleaseDataColumn::Table.name(); let rd_table = ReleaseDataColumn::Table.name();
let rd_insert_columns = format!( let rd_insert_columns = format!(
"({}, {}, {})", "({}, {}, {}, {})",
ReleaseDataColumn::Name.name(), ReleaseDataColumn::Name.name(),
ReleaseDataColumn::DataType.name(), ReleaseDataColumn::DataType.name(),
ReleaseDataColumn::Options.name(),
ReleaseDataColumn::UserId.name(), ReleaseDataColumn::UserId.name(),
); );
let rd_insert_clause = let rd_insert_clause = format!(
format!("INSERT INTO {rd_table} {rd_insert_columns} VALUES ($1, $2, $3) RETURNING *"); "INSERT INTO {rd_table} {rd_insert_columns} VALUES ($1, $2, $3, $4) RETURNING *"
);
let mut rd = sqlx::query_as::<_, ReleaseDataModel>(&rd_insert_clause) let mut rd = sqlx::query_as::<_, ReleaseDataModel>(&rd_insert_clause)
.bind(name) .bind(name)
.bind(draft.data_type as i32) .bind(draft.data_type as i32)
.bind(draft.options)
.bind(draft.user_id) .bind(draft.user_id)
.fetch_one(&mut *tx) .fetch_one(&mut *tx)
.await?; .await?;
@ -239,7 +242,7 @@ impl ReleaseDataAccessor for RtssDbAccessor {
)); ));
} }
// 查询默认发布数据 // 查询默认发布数据
let mut rd = self let rd = self
.query_release_data_by_id(draft.default_release_data_id.unwrap()) .query_release_data_by_id(draft.default_release_data_id.unwrap())
.await?; .await?;
// 开启事务 // 开启事务
@ -266,18 +269,19 @@ impl ReleaseDataAccessor for RtssDbAccessor {
// 更新发布数据使用的版本 // 更新发布数据使用的版本
let rd_table = ReleaseDataColumn::Table.name(); let rd_table = ReleaseDataColumn::Table.name();
let used_version_id = ReleaseDataColumn::UsedVersionId.name(); let used_version_id = ReleaseDataColumn::UsedVersionId.name();
let rd_options = ReleaseDataColumn::Options.name();
let rd_updated_at = ReleaseDataColumn::UpdatedAt.name(); let rd_updated_at = ReleaseDataColumn::UpdatedAt.name();
let rd_id = ReleaseDataColumn::Id.name(); let rd_id = ReleaseDataColumn::Id.name();
let rd_update_clause = let rd_update_clause =
format!("UPDATE {rd_table} SET {used_version_id} = $1, {rd_updated_at} = 'now()' WHERE {rd_id} = $2"); format!("UPDATE {rd_table} SET {used_version_id} = $1, {rd_options} = $2, {rd_updated_at} = 'now()' WHERE {rd_id} = $3 RETURNING *");
sqlx::query(&rd_update_clause) let rd = sqlx::query_as::<_, ReleaseDataModel>(&rd_update_clause)
.bind(rdv.id) .bind(rdv.id)
.bind(draft.options.clone())
.bind(rd.id) .bind(rd.id)
.execute(&mut *tx) .fetch_one(&mut *tx)
.await?; .await?;
// 成功后提交事务 // 成功后提交事务
tx.commit().await?; tx.commit().await?;
rd.used_version_id = Some(rdv.id);
Ok((rd, rdv)) Ok((rd, rdv))
} }
@ -350,17 +354,16 @@ impl ReleaseDataAccessor for RtssDbAccessor {
let rdv_table = ReleaseDataVersionColumn::Table.name(); let rdv_table = ReleaseDataVersionColumn::Table.name();
// 查询列除了data列 // 查询列除了data列
let rdv_columns = format!( let rdv_columns = format!(
"{}, {}, {}, {}, {}, {}", "{}, {}, {}, {}, {}",
ReleaseDataVersionColumn::Id.name(), ReleaseDataVersionColumn::Id.name(),
ReleaseDataVersionColumn::ReleaseDataId.name(), ReleaseDataVersionColumn::ReleaseDataId.name(),
ReleaseDataVersionColumn::Version.name(),
ReleaseDataVersionColumn::Description.name(), ReleaseDataVersionColumn::Description.name(),
ReleaseDataVersionColumn::UserId.name(), ReleaseDataVersionColumn::UserId.name(),
ReleaseDataVersionColumn::CreatedAt.name(), ReleaseDataVersionColumn::CreatedAt.name(),
); );
let rdv_release_id = ReleaseDataVersionColumn::ReleaseDataId.name(); let rdv_release_id = ReleaseDataVersionColumn::ReleaseDataId.name();
// 按版本号倒序排序 // 按版本号倒序排序
let sort = Sort::new(ReleaseDataVersionColumn::Version, SortOrder::Desc); let sort = Sort::new(ReleaseDataVersionColumn::Id, SortOrder::Desc);
let order_by_clause = sort.to_order_by_clause(); let order_by_clause = sort.to_order_by_clause();
let rdv_query_clause = format!( let rdv_query_clause = format!(
"SELECT {rdv_columns} FROM {rdv_table} WHERE {rdv_release_id} = $1 {order_by_clause}", "SELECT {rdv_columns} FROM {rdv_table} WHERE {rdv_release_id} = $1 {order_by_clause}",
@ -507,7 +510,9 @@ mod tests {
use crate::{CreateDraftData, DraftDataAccessor, RtssDbAccessor}; use crate::{CreateDraftData, DraftDataAccessor, RtssDbAccessor};
use super::*; use super::*;
use rtss_dto::common::IscsStyle;
use rtss_log::tracing::Level; use rtss_log::tracing::Level;
use serde::{Deserialize, Serialize};
use sqlx::PgPool; use sqlx::PgPool;
#[test] #[test]
@ -543,6 +548,11 @@ mod tests {
assert_eq!(query_with_all.build_filter(), expects); assert_eq!(query_with_all.build_filter(), expects);
} }
#[derive(Debug, Serialize, Deserialize)]
pub struct IscsDataOptions {
pub style: IscsStyle,
}
// You could also do `use foo_crate::MIGRATOR` and just refer to it as `MIGRATOR` here. // You could also do `use foo_crate::MIGRATOR` and just refer to it as `MIGRATOR` here.
#[sqlx::test(migrator = "crate::MIGRATOR")] #[sqlx::test(migrator = "crate::MIGRATOR")]
async fn test_basic_use(pool: PgPool) -> Result<(), DbAccessError> { async fn test_basic_use(pool: PgPool) -> Result<(), DbAccessError> {
@ -552,7 +562,14 @@ mod tests {
let data = "test".as_bytes(); let data = "test".as_bytes();
let draft = accessor let draft = accessor
.create_draft_data( .create_draft_data(
CreateDraftData::new("test", rtss_dto::common::DataType::Em, 1).with_data(data), CreateDraftData::new("test", rtss_dto::common::DataType::Iscs, 1)
.with_options(
serde_json::to_value(IscsDataOptions {
style: IscsStyle::DaShiZhiNeng,
})
.unwrap(),
)
.with_data(data),
) )
.await?; .await?;
let name = "test_release"; let name = "test_release";
@ -576,6 +593,10 @@ mod tests {
assert_eq!(release_data.name, name); assert_eq!(release_data.name, name);
// 检查使用版本是刚刚发布的版本 // 检查使用版本是刚刚发布的版本
assert_eq!(release_data.used_version_id, Some(version1.id)); assert_eq!(release_data.used_version_id, Some(version1.id));
// 检查options数据
let options: IscsDataOptions =
serde_json::from_value(release_data.options.unwrap()).unwrap();
assert_eq!(options.style, IscsStyle::DaShiZhiNeng);
// 检查版本数据 // 检查版本数据
assert_eq!(version1.data, data); assert_eq!(version1.data, data);
// 检查版本描述 // 检查版本描述
@ -694,7 +715,7 @@ mod tests {
let query = ReleaseDataQuery::new().with_data_type(rtss_dto::common::DataType::Em); let query = ReleaseDataQuery::new().with_data_type(rtss_dto::common::DataType::Em);
let page = PageQuery::new(1, 10); let page = PageQuery::new(1, 10);
let page_result = accessor.query_release_data_list(query, page).await?; let page_result = accessor.query_release_data_list(query, page).await?;
assert_eq!(page_result.total, 9); assert_eq!(page_result.total, 8);
println!("分页查询发布数据测试成功"); println!("分页查询发布数据测试成功");
Ok(()) Ok(())

View File

@ -74,7 +74,6 @@ pub(crate) enum ReleaseDataVersionColumn {
Id, Id,
ReleaseDataId, ReleaseDataId,
Data, Data,
Version,
Description, Description,
UserId, UserId,
CreatedAt, CreatedAt,
@ -86,7 +85,6 @@ pub struct ReleaseDataVersionModel {
pub release_data_id: i32, pub release_data_id: i32,
#[sqlx(default)] #[sqlx(default)]
pub data: Vec<u8>, pub data: Vec<u8>,
pub version: i32,
pub description: String, pub description: String,
pub user_id: i32, pub user_id: i32,
pub created_at: DateTime<Local>, pub created_at: DateTime<Local>,
@ -243,7 +241,6 @@ impl TableColumn for ReleaseDataVersionColumn {
ReleaseDataVersionColumn::Id => "id", ReleaseDataVersionColumn::Id => "id",
ReleaseDataVersionColumn::ReleaseDataId => "release_data_id", ReleaseDataVersionColumn::ReleaseDataId => "release_data_id",
ReleaseDataVersionColumn::Data => "data", ReleaseDataVersionColumn::Data => "data",
ReleaseDataVersionColumn::Version => "version",
ReleaseDataVersionColumn::Description => "description", ReleaseDataVersionColumn::Description => "description",
ReleaseDataVersionColumn::UserId => "user_id", ReleaseDataVersionColumn::UserId => "user_id",
ReleaseDataVersionColumn::CreatedAt => "created_at", ReleaseDataVersionColumn::CreatedAt => "created_at",

View File

@ -90,7 +90,6 @@ CREATE TABLE
id SERIAL PRIMARY KEY, -- id 自增主键 id SERIAL PRIMARY KEY, -- id 自增主键
release_data_id INT NOT NULL, -- 发布数据id release_data_id INT NOT NULL, -- 发布数据id
data BYTEA NOT NULL, -- 数据 data BYTEA NOT NULL, -- 数据
version SERIAL NOT NULL, -- 版本号
description TEXT NOT NULL, -- 版本描述 description TEXT NOT NULL, -- 版本描述
user_id INT NOT NULL, -- 发布用户id user_id INT NOT NULL, -- 发布用户id
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间 created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 创建时间
@ -113,8 +112,6 @@ COMMENT ON COLUMN rtss.release_data_version.release_data_id IS '发布数据id';
COMMENT ON COLUMN rtss.release_data_version.data IS '数据'; COMMENT ON COLUMN rtss.release_data_version.data IS '数据';
COMMENT ON COLUMN rtss.release_data_version.version IS '版本号';
COMMENT ON COLUMN rtss.release_data_version.description IS '版本描述'; COMMENT ON COLUMN rtss.release_data_version.description IS '版本描述';
COMMENT ON COLUMN rtss.release_data_version.user_id IS '发布用户id'; COMMENT ON COLUMN rtss.release_data_version.user_id IS '发布用户id';