diff --git a/crates/rtss_api/src/apis/draft_data.rs b/crates/rtss_api/src/apis/draft_data.rs index e4eee99..6835737 100644 --- a/crates/rtss_api/src/apis/draft_data.rs +++ b/crates/rtss_api/src/apis/draft_data.rs @@ -38,9 +38,10 @@ impl DraftDataQuery { &self, ctx: &Context<'ctx>, paging: PageQueryDto, - query: UserDraftDataFilterDto, + mut query: UserDraftDataFilterDto, ) -> async_graphql::Result> { let db_accessor = ctx.data::()?; + query.data_type = Some(DataType::Iscs); let paging_result = db_accessor .query_draft_data(query.into(), paging.into()) .await?; @@ -51,9 +52,10 @@ impl DraftDataQuery { &self, ctx: &Context<'ctx>, paging: PageQueryDto, - query: SharedDraftDataFilterDto, + mut query: SharedDraftDataFilterDto, ) -> async_graphql::Result> { let db_accessor = ctx.data::()?; + query.data_type = Some(DataType::Iscs); let paging_result = db_accessor .query_draft_data(query.into(), paging.into()) .await?; @@ -187,6 +189,7 @@ impl From> for rtss_db::CreateDraftData { pub struct UserDraftDataFilterDto { pub user_id: i32, pub name: Option, + /// 数据类型,在某个具体类型查询时不传,传了也不生效 pub data_type: Option, pub options: Option, pub is_shared: Option, @@ -211,7 +214,8 @@ impl From> for rtss_db::DraftDataQuery pub struct SharedDraftDataFilterDto { pub user_id: Option, pub name: Option, - pub data_type: Option, + /// 数据类型,在某个具体类型查询时不传,传了也不生效 + pub data_type: Option, pub options: Option, } @@ -252,7 +256,7 @@ impl From for rtss_db::DraftDataQuery { pub struct DraftDataDto { pub id: i32, pub name: String, - pub data_type: rtss_dto::common::DataType, + pub data_type: DataType, pub options: Option, /// base64编码的数据 pub data: Option, diff --git a/crates/rtss_api/src/apis/mod.rs b/crates/rtss_api/src/apis/mod.rs index f99b007..ec86a5b 100644 --- a/crates/rtss_api/src/apis/mod.rs +++ b/crates/rtss_api/src/apis/mod.rs @@ -43,6 +43,10 @@ impl From for rtss_db::common::PageQuery { #[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 = "ReleaseDataVersionPageDto", + params(release_data::ReleaseDataVersionDto) +))] #[graphql(concrete( name = "ReleaseIscsDataPageDto", params(release_data::ReleaseIscsDataWithoutVersionDto) diff --git a/crates/rtss_api/src/apis/release_data.rs b/crates/rtss_api/src/apis/release_data.rs index f066ec8..01e30d8 100644 --- a/crates/rtss_api/src/apis/release_data.rs +++ b/crates/rtss_api/src/apis/release_data.rs @@ -6,7 +6,9 @@ use rtss_db::{model::ReleaseDataModel, ReleaseDataAccessor, RtssDbAccessor}; use rtss_dto::common::DataType; use serde_json::Value; -use super::common::IscsDataOptions; +use crate::apis::draft_data::DraftDataDto; + +use super::common::{DataOptions, IscsDataOptions}; use super::{PageDto, PageQueryDto}; #[derive(Default)] @@ -36,16 +38,17 @@ impl ReleaseDataQuery { &self, ctx: &Context<'_>, page: PageQueryDto, - query: UserReleaseDataFilterDto, + mut query: UserReleaseDataFilterDto, ) -> async_graphql::Result> { let db_accessor = ctx.data::()?; + query.data_type = Some(DataType::Iscs); let paging = db_accessor .query_release_data_list(query.into(), page.into()) .await?; Ok(paging.into()) } - /// id查询发布数据 + /// id查询发布数据及当前使用的版本数据 async fn release_data( &self, ctx: &Context<'_>, @@ -55,6 +58,33 @@ impl ReleaseDataQuery { let model = db_accessor.query_release_data_with_used_version(id).await?; Ok(model.into()) } + + /// 查询发布数据的版本 + async fn release_data_version_paging( + &self, + ctx: &Context<'_>, + data_id: i32, + page: PageQueryDto, + ) -> async_graphql::Result> { + let db_accessor = ctx.data::()?; + let paging = db_accessor + .query_release_data_version_list(data_id, page.into()) + .await?; + Ok(paging.into()) + } + + /// 根据id获取发布数据版本详情 + async fn release_data_version( + &self, + ctx: &Context<'_>, + version_id: i32, + ) -> async_graphql::Result { + let db_accessor = ctx.data::()?; + let model = db_accessor + .query_release_data_version_by_id(version_id) + .await?; + Ok(model.into()) + } } #[Object] @@ -87,6 +117,60 @@ impl ReleaseDataMutation { .await?; Ok(result.into()) } + + /// 更新发布数据name + async fn update_release_data_name( + &self, + ctx: &Context<'_>, + id: i32, + name: String, + ) -> async_graphql::Result { + let db_accessor = ctx.data::()?; + let result = db_accessor.update_release_data_name(id, &name).await?; + Ok(result.into()) + } + + /// 上下架发布数据 + async fn update_release_data_published( + &self, + ctx: &Context<'_>, + id: i32, + is_published: bool, + ) -> async_graphql::Result { + let db_accessor = ctx.data::()?; + let result = db_accessor + .set_release_data_published(id, is_published) + .await?; + Ok(result.into()) + } + + /// 更新发布数据使用的版本 + async fn update_release_data_used_version( + &self, + ctx: &Context<'_>, + id: i32, + version_id: i32, + ) -> async_graphql::Result { + let db_accessor = ctx.data::()?; + let result = db_accessor + .set_release_data_used_version(id, version_id) + .await?; + Ok(result.into()) + } + + /// 从发布数据版本中创建草稿数据 + async fn create_draft_data_from_release_data_version( + &self, + ctx: &Context<'_>, + release_data_id: i32, + version_id: i32, + ) -> async_graphql::Result { + let db_accessor = ctx.data::()?; + let result = db_accessor + .create_draft_from_release_version(release_data_id, version_id) + .await?; + Ok(result.into()) + } } #[derive(Debug, InputObject)] @@ -98,15 +182,18 @@ pub struct ReleaseDataFilterDto { } #[derive(Debug, InputObject)] -pub struct UserReleaseDataFilterDto { +#[graphql(concrete(name = "UserReleaseIscsDataFilterDto", params(IscsDataOptions)))] +pub struct UserReleaseDataFilterDto { pub user_id: i32, pub name: Option, + /// 数据类型,在某个具体类型查询时不传,传了也不生效 pub data_type: Option, + pub options: Option, pub is_published: Option, } -impl From for rtss_db::ReleaseDataQuery { - fn from(value: UserReleaseDataFilterDto) -> Self { +impl From> for rtss_db::ReleaseDataQuery { + fn from(value: UserReleaseDataFilterDto) -> Self { Self { name: value.name, user_id: Some(value.user_id), @@ -131,7 +218,7 @@ impl From for rtss_db::ReleaseDataQuery { pub struct ReleaseDataDto { pub id: i32, pub name: String, - pub data_type: String, + pub data_type: DataType, pub options: Option, pub used_version_id: Option, pub user_id: i32, @@ -168,6 +255,7 @@ pub struct ReleaseDataWithUsedVersionDto { pub struct ReleaseDataVersionDto { pub id: i32, pub release_data_id: i32, + pub options: Option, pub description: String, /// base64编码的数据 pub data: String, @@ -189,6 +277,7 @@ impl From for ReleaseDataVersionDto { Self { id: model.id, release_data_id: model.release_data_id, + options: model.options, description: model.description, data: BASE64_STANDARD.encode(model.data), user_id: model.user_id, @@ -202,7 +291,7 @@ impl From for ReleaseDataDto { Self { id: model.id, name: model.name, - data_type: model.data_type.to_string(), + data_type: DataType::try_from(model.data_type).unwrap(), options: model.options, used_version_id: model.used_version_id, user_id: model.user_id, diff --git a/crates/rtss_db/src/db_access/draft_data.rs b/crates/rtss_db/src/db_access/draft_data.rs index 9f2116e..9d93d07 100644 --- a/crates/rtss_db/src/db_access/draft_data.rs +++ b/crates/rtss_db/src/db_access/draft_data.rs @@ -163,6 +163,11 @@ impl CreateDraftData { } } + pub fn with_option_options(mut self, options: Option) -> Self { + self.options = options; + self + } + pub fn with_options(mut self, options: Value) -> Self { self.options = Some(options); self diff --git a/crates/rtss_db/src/db_access/release_data.rs b/crates/rtss_db/src/db_access/release_data.rs index f291800..68eb809 100644 --- a/crates/rtss_db/src/db_access/release_data.rs +++ b/crates/rtss_db/src/db_access/release_data.rs @@ -1,5 +1,5 @@ use rtss_dto::common::DataType; -use sqlx::types::chrono; +use sqlx::{types::chrono, Postgres}; use crate::{ common::{PageQuery, PageResult, Sort, SortOrder, TableColumn}, @@ -41,10 +41,11 @@ pub trait ReleaseDataAccessor { release_id: i32, ) -> Result; /// 查询发布数据所有版本信息 - async fn query_release_data_versions( + async fn query_release_data_version_list( &self, release_id: i32, - ) -> Result, DbAccessError>; + page: PageQuery, + ) -> Result, DbAccessError>; /// 根据id查询发布版本数据 async fn query_release_data_version_by_id( &self, @@ -68,13 +69,13 @@ pub trait ReleaseDataAccessor { is_published: bool, ) -> Result; /// 设置在使用的版本 - async fn set_used_version( + async fn set_release_data_used_version( &self, release_id: i32, version_id: i32, ) -> Result; /// 从指定的版本数据创建草稿 - async fn create_draft_from_version( + async fn create_draft_from_release_version( &self, version_id: i32, user_id: i32, @@ -157,6 +158,49 @@ impl ReleaseDataQuery { } } +pub struct CreateReleaseVersionData { + pub release_data_id: i32, + pub options: Option, + pub data: Vec, + pub description: String, + pub user_id: i32, +} + +impl RtssDbAccessor { + async fn insert_release_data_version<'e, 'c: 'e, E>( + &self, + data: CreateReleaseVersionData, + executor: E, + ) -> Result + where + E: 'e + sqlx::Executor<'c, Database = Postgres>, + { + let rdv_table = ReleaseDataVersionColumn::Table.name(); + let rdv_insert_columns = format!( + "{}, {}, {}, {}, {}", + ReleaseDataVersionColumn::ReleaseDataId.name(), + ReleaseDataVersionColumn::Options.name(), + ReleaseDataVersionColumn::Data.name(), + ReleaseDataVersionColumn::Description.name(), + ReleaseDataVersionColumn::UserId.name(), + ); + let rdv_insert_clause = format!( + "INSERT INTO {rdv_table} ({rdv_insert_columns}) VALUES ($1, $2, $3, $4, $5) RETURNING *", + rdv_table = rdv_table, + rdv_insert_columns = rdv_insert_columns + ); + let rdv = sqlx::query_as::<_, ReleaseDataVersionModel>(&rdv_insert_clause) + .bind(data.release_data_id) + .bind(data.options) + .bind(data.data) + .bind(data.description) + .bind(data.user_id) + .fetch_one(executor) + .await?; + Ok(rdv) + } +} + impl ReleaseDataAccessor for RtssDbAccessor { async fn release_new_from_draft( &self, @@ -172,6 +216,9 @@ impl ReleaseDataAccessor for RtssDbAccessor { let mut tx = self.pool.begin().await?; // 查询草稿数据 let draft = self.query_draft_data_by_id(draft_id).await?; + if draft.data.is_none() { + return Err(DbAccessError::DataError("草稿数据为空".to_string())); + } // 创建发布数据 let rd_table = ReleaseDataColumn::Table.name(); let rd_insert_columns = format!( @@ -187,28 +234,22 @@ impl ReleaseDataAccessor for RtssDbAccessor { let mut rd = sqlx::query_as::<_, ReleaseDataModel>(&rd_insert_clause) .bind(name) .bind(draft.data_type as i32) - .bind(draft.options) + .bind(draft.options.clone()) .bind(draft.user_id) .fetch_one(&mut *tx) .await?; // 创建发布数据版本 - let rdv_table = ReleaseDataVersionColumn::Table.name(); - let rdv_insert_columns = format!( - "{}, {}, {}, {}", - ReleaseDataVersionColumn::ReleaseDataId.name(), - ReleaseDataVersionColumn::Data.name(), - ReleaseDataVersionColumn::Description.name(), - ReleaseDataVersionColumn::UserId.name(), - ); - let rdv_insert_clause = format!( - "INSERT INTO {rdv_table} ({rdv_insert_columns}) VALUES ($1, $2, $3, $4) RETURNING *" - ); - let rdv = sqlx::query_as::<_, ReleaseDataVersionModel>(&rdv_insert_clause) - .bind(rd.id) - .bind(draft.data) - .bind(description) - .bind(draft.user_id) - .fetch_one(&mut *tx) + let rdv = self + .insert_release_data_version( + CreateReleaseVersionData { + release_data_id: rd.id, + options: draft.options.clone(), + data: draft.data.unwrap(), + description: description.to_string(), + user_id: draft.user_id, + }, + &mut *tx, + ) .await?; // 更新发布数据使用的版本 let used_version_id = ReleaseDataColumn::UsedVersionId.name(); @@ -241,6 +282,9 @@ impl ReleaseDataAccessor for RtssDbAccessor { "草稿未设置默认发布数据".to_string(), )); } + if draft.data.is_none() { + return Err(DbAccessError::DataError("草稿数据为空".to_string())); + } // 查询默认发布数据 let rd = self .query_release_data_by_id(draft.default_release_data_id.unwrap()) @@ -248,23 +292,17 @@ impl ReleaseDataAccessor for RtssDbAccessor { // 开启事务 let mut tx = self.pool.begin().await?; // 创建发布数据版本 - let rdv_table = ReleaseDataVersionColumn::Table.name(); - let rdv_insert_columns = format!( - "{}, {}, {}, {}", - ReleaseDataVersionColumn::ReleaseDataId.name(), - ReleaseDataVersionColumn::Data.name(), - ReleaseDataVersionColumn::Description.name(), - ReleaseDataVersionColumn::UserId.name(), - ); - let rdv_insert_clause = format!( - "INSERT INTO {rdv_table} ({rdv_insert_columns}) VALUES ($1, $2, $3, $4) RETURNING *" - ); - let rdv = sqlx::query_as::<_, ReleaseDataVersionModel>(&rdv_insert_clause) - .bind(rd.id) - .bind(draft.data) - .bind(description) - .bind(draft.user_id) - .fetch_one(&mut *tx) + let rdv = self + .insert_release_data_version( + CreateReleaseVersionData { + release_data_id: rd.id, + options: draft.options.clone(), + data: draft.data.unwrap(), + description: description.to_string(), + user_id: draft.user_id, + }, + &mut *tx, + ) .await?; // 更新发布数据使用的版本 let rd_table = ReleaseDataColumn::Table.name(); @@ -346,17 +384,29 @@ impl ReleaseDataAccessor for RtssDbAccessor { Ok(rd) } - async fn query_release_data_versions( + async fn query_release_data_version_list( &self, release_id: i32, - ) -> Result, DbAccessError> { + page: PageQuery, + ) -> Result, DbAccessError> { // 查询发布数据版本 let rdv_table = ReleaseDataVersionColumn::Table.name(); + // let where_clause = query.build_filter(); + let count_clause = format!("SELECT COUNT(*) FROM {rdv_table}"); + + // 查询总数 + let total = sqlx::query_scalar(&count_clause) + .fetch_one(&self.pool) + .await?; + if total == 0 { + return Ok(PageResult::new(0, vec![])); + } // 查询列,除了data列 let rdv_columns = format!( - "{}, {}, {}, {}, {}", + "{}, {}, {}, {}, {}, {}", ReleaseDataVersionColumn::Id.name(), ReleaseDataVersionColumn::ReleaseDataId.name(), + ReleaseDataVersionColumn::Options.name(), ReleaseDataVersionColumn::Description.name(), ReleaseDataVersionColumn::UserId.name(), ReleaseDataVersionColumn::CreatedAt.name(), @@ -365,14 +415,15 @@ impl ReleaseDataAccessor for RtssDbAccessor { // 按版本号倒序排序 let sort = Sort::new(ReleaseDataVersionColumn::Id, SortOrder::Desc); let order_by_clause = sort.to_order_by_clause(); + let paging_clause = page.to_limit_clause(); 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} {paging_clause}", ); - let rdv = sqlx::query_as::<_, ReleaseDataVersionModel>(&rdv_query_clause) + let data = sqlx::query_as::<_, ReleaseDataVersionModel>(&rdv_query_clause) .bind(release_id) .fetch_all(&self.pool) .await?; - Ok(rdv) + Ok(PageResult::new(total, data)) } async fn query_release_data_version_by_id( @@ -456,7 +507,7 @@ impl ReleaseDataAccessor for RtssDbAccessor { Ok(rd) } - async fn set_used_version( + async fn set_release_data_used_version( &self, release_id: i32, version_id: i32, @@ -482,7 +533,7 @@ impl ReleaseDataAccessor for RtssDbAccessor { Ok(rd) } - async fn create_draft_from_version( + async fn create_draft_from_release_version( &self, version_id: i32, user_id: i32, @@ -497,6 +548,7 @@ impl ReleaseDataAccessor for RtssDbAccessor { let draft = self .create_draft_data( CreateDraftData::new(&name, DataType::try_from(rd.data_type).unwrap(), user_id) + .with_option_options(rdv.options) .with_data(&rdv.data) .with_default_release_data_id(rd.id), ) @@ -643,7 +695,7 @@ mod tests { // 设置使用的版本 let release_data = accessor - .set_used_version(release_data.id, version1.id) + .set_release_data_used_version(release_data.id, version1.id) .await?; assert_eq!(release_data.used_version_id, Some(version1.id)); assert!(release_data.updated_at > release_data.created_at); @@ -651,9 +703,15 @@ mod tests { // 查询发布数据所有版本 let versions = accessor - .query_release_data_versions(release_data.id) + .query_release_data_version_list( + release_data.id, + PageQuery { + page: 1, + items_per_page: 10, + }, + ) .await?; - assert_eq!(versions.len(), 2); + assert_eq!(versions.total, 2); println!("查询发布数据所有版本测试成功: {:?}", versions); // 查询发布数据详情 @@ -665,11 +723,15 @@ mod tests { // 从版本创建草稿 let draft = accessor - .create_draft_from_version(used_version.id, 1) + .create_draft_from_release_version(used_version.id, 1) .await?; assert_eq!(draft.data, Some(used_version.data)); assert_eq!(draft.default_release_data_id, Some(release_data.id)); - println!("从版本创建草稿测试成功"); + assert_eq!(draft.options, used_version.options); + println!( + "从版本创建草稿测试成功: draft_data.options = {:?}", + draft.options + ); // 构造分页查询所需发布数据,4个人每人发布2个数据 for i in 2..6 { diff --git a/crates/rtss_db/src/model.rs b/crates/rtss_db/src/model.rs index cc3c397..3c633e0 100644 --- a/crates/rtss_db/src/model.rs +++ b/crates/rtss_db/src/model.rs @@ -58,6 +58,7 @@ pub struct ReleaseDataModel { pub id: i32, pub name: String, pub data_type: i32, + /// 从发布版本复制的选项,主要用于查询 #[sqlx(default)] pub options: Option, pub used_version_id: Option, @@ -73,6 +74,7 @@ pub(crate) enum ReleaseDataVersionColumn { Table, Id, ReleaseDataId, + Options, Data, Description, UserId, @@ -84,6 +86,8 @@ pub struct ReleaseDataVersionModel { pub id: i32, pub release_data_id: i32, #[sqlx(default)] + pub options: Option, + #[sqlx(default)] pub data: Vec, pub description: String, pub user_id: i32, @@ -240,6 +244,7 @@ impl TableColumn for ReleaseDataVersionColumn { ReleaseDataVersionColumn::Table => "rtss.release_data_version", ReleaseDataVersionColumn::Id => "id", ReleaseDataVersionColumn::ReleaseDataId => "release_data_id", + ReleaseDataVersionColumn::Options => "options", ReleaseDataVersionColumn::Data => "data", ReleaseDataVersionColumn::Description => "description", ReleaseDataVersionColumn::UserId => "user_id", diff --git a/migrations/20240830095636_init.up.sql b/migrations/20240830095636_init.up.sql index 1c40a86..4478cda 100644 --- a/migrations/20240830095636_init.up.sql +++ b/migrations/20240830095636_init.up.sql @@ -89,6 +89,7 @@ CREATE TABLE rtss.release_data_version ( id SERIAL PRIMARY KEY, -- id 自增主键 release_data_id INT NOT NULL, -- 发布数据id + options JSONB NULL, -- 数据相关的参数项或配置项 data BYTEA NOT NULL, -- 数据 description TEXT NOT NULL, -- 版本描述 user_id INT NOT NULL, -- 发布用户id @@ -110,6 +111,8 @@ COMMENT ON COLUMN rtss.release_data_version.id IS 'id 自增主键'; COMMENT ON COLUMN rtss.release_data_version.release_data_id IS '发布数据id'; +COMMENT ON COLUMN rtss.release_data_version.options IS '数据相关的参数项或配置项'; + COMMENT ON COLUMN rtss.release_data_version.data IS '数据'; COMMENT ON COLUMN rtss.release_data_version.description IS '版本描述';