实现配置项相关的CRUD 调整草稿数据管理接口
This commit is contained in:
parent
875788a71d
commit
2a7a2ffc99
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -11,6 +11,7 @@
|
|||||||
"Joylink",
|
"Joylink",
|
||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
"mplj",
|
"mplj",
|
||||||
|
"Neng",
|
||||||
"plpgsql",
|
"plpgsql",
|
||||||
"prost",
|
"prost",
|
||||||
"proto",
|
"proto",
|
||||||
|
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -2199,6 +2199,8 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"rtss_dto",
|
"rtss_dto",
|
||||||
"rtss_log",
|
"rtss_log",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
@ -2210,6 +2212,7 @@ dependencies = [
|
|||||||
"async-graphql",
|
"async-graphql",
|
||||||
"prost",
|
"prost",
|
||||||
"prost-build",
|
"prost-build",
|
||||||
|
"serde",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ sqlx = { version = "0.8", features = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
] }
|
] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0.125"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -6,8 +6,8 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
|
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
|
||||||
serde = { version = "1.0.208", features = ["derive"] }
|
serde = { workspace = true }
|
||||||
serde_json = "1.0.125"
|
serde_json = { workspace = true }
|
||||||
chrono = { version = "0.4.38", features = ["serde"] }
|
chrono = { version = "0.4.38", features = ["serde"] }
|
||||||
axum = "0.7.5"
|
axum = "0.7.5"
|
||||||
axum-extra = { version = "0.9.3", features = ["typed-header"] }
|
axum-extra = { version = "0.9.3", features = ["typed-header"] }
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
use async_graphql::{Context, InputObject, Object, SimpleObject};
|
use async_graphql::{Context, InputObject, Object, SimpleObject};
|
||||||
|
use async_graphql::{InputType, OutputType};
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
|
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;
|
use rtss_dto::common::{DataType, IscsStyle};
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::pagination::PageQueryDto;
|
use crate::pagination::PageQueryDto;
|
||||||
|
|
||||||
@ -28,12 +33,12 @@ impl DraftDataQuery {
|
|||||||
Ok(paging_result.into())
|
Ok(paging_result.into())
|
||||||
}
|
}
|
||||||
/// 分页查询用户的草稿数据
|
/// 分页查询用户的草稿数据
|
||||||
async fn user_draft_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,
|
query: UserDraftDataFilterDto<IscsDataOptions>,
|
||||||
) -> async_graphql::Result<DraftDataPage> {
|
) -> async_graphql::Result<DraftIscsDataPage> {
|
||||||
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())
|
||||||
@ -41,12 +46,12 @@ impl DraftDataQuery {
|
|||||||
Ok(paging_result.into())
|
Ok(paging_result.into())
|
||||||
}
|
}
|
||||||
/// 分页查询共享的草稿数据
|
/// 分页查询共享的草稿数据
|
||||||
async fn shared_draft_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,
|
query: SharedDraftDataFilterDto<IscsDataOptions>,
|
||||||
) -> async_graphql::Result<DraftDataPage> {
|
) -> async_graphql::Result<DraftIscsDataPage> {
|
||||||
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())
|
||||||
@ -54,7 +59,11 @@ impl DraftDataQuery {
|
|||||||
Ok(paging_result.into())
|
Ok(paging_result.into())
|
||||||
}
|
}
|
||||||
/// 根据id获取草稿数据
|
/// 根据id获取草稿数据
|
||||||
async fn draft_data(&self, ctx: &Context<'_>, id: i32) -> async_graphql::Result<DraftData> {
|
async fn draft_data(
|
||||||
|
&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())
|
||||||
@ -74,12 +83,12 @@ impl DraftDataQuery {
|
|||||||
|
|
||||||
#[Object]
|
#[Object]
|
||||||
impl DraftDataMutation {
|
impl DraftDataMutation {
|
||||||
/// 创建草稿数据
|
/// 创建草稿ISCS数据
|
||||||
async fn create_draft_data(
|
async fn create_draft_iscs_data(
|
||||||
&self,
|
&self,
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
input: CreateDraftDataDto,
|
input: CreateDraftDataDto<IscsDataOptions>,
|
||||||
) -> async_graphql::Result<DraftData> {
|
) -> async_graphql::Result<DraftData<IscsDataOptions>> {
|
||||||
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())
|
||||||
@ -90,7 +99,7 @@ impl DraftDataMutation {
|
|||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
id: i32,
|
id: i32,
|
||||||
name: String,
|
name: String,
|
||||||
) -> async_graphql::Result<DraftData> {
|
) -> async_graphql::Result<DraftDataWithStringOptions> {
|
||||||
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())
|
||||||
@ -101,7 +110,7 @@ impl DraftDataMutation {
|
|||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
id: i32,
|
id: i32,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
) -> async_graphql::Result<DraftData> {
|
) -> async_graphql::Result<DraftDataWithStringOptions> {
|
||||||
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
let db_accessor = ctx.data::<RtssDbAccessor>()?;
|
||||||
let draft_data = db_accessor
|
let draft_data = db_accessor
|
||||||
.update_draft_data_data(id, data.as_slice())
|
.update_draft_data_data(id, data.as_slice())
|
||||||
@ -114,7 +123,7 @@ impl DraftDataMutation {
|
|||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
id: i32,
|
id: i32,
|
||||||
is_shared: bool,
|
is_shared: bool,
|
||||||
) -> async_graphql::Result<DraftData> {
|
) -> async_graphql::Result<DraftDataWithStringOptions> {
|
||||||
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())
|
||||||
@ -135,7 +144,7 @@ impl DraftDataMutation {
|
|||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
id: i32,
|
id: i32,
|
||||||
release_data_id: i32,
|
release_data_id: i32,
|
||||||
) -> async_graphql::Result<DraftData> {
|
) -> async_graphql::Result<DraftDataWithStringOptions> {
|
||||||
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)
|
||||||
@ -149,7 +158,7 @@ impl DraftDataMutation {
|
|||||||
id: i32,
|
id: i32,
|
||||||
name: String,
|
name: String,
|
||||||
user_id: i32,
|
user_id: i32,
|
||||||
) -> async_graphql::Result<DraftData> {
|
) -> async_graphql::Result<DraftDataWithStringOptions> {
|
||||||
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())
|
||||||
@ -157,54 +166,87 @@ impl DraftDataMutation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, InputObject)]
|
#[derive(Debug, InputObject)]
|
||||||
pub struct CreateDraftDataDto {
|
#[graphql(concrete(name = "CreateDraftIscsDto", params(IscsDataOptions)))]
|
||||||
|
pub struct CreateDraftDataDto<T: DataOptions> {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub data_type: rtss_dto::common::DataType,
|
pub options: Option<T>,
|
||||||
pub data: Vec<u8>,
|
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CreateDraftDataDto> for rtss_db::CreateDraftData {
|
impl<T: DataOptions> From<CreateDraftDataDto<T>> for rtss_db::CreateDraftData {
|
||||||
fn from(value: CreateDraftDataDto) -> Self {
|
fn from(value: CreateDraftDataDto<T>) -> Self {
|
||||||
Self::new(&value.name, value.data_type, value.user_id).with_data(value.data.as_slice())
|
let cdd = Self::new(&value.name, DataType::Iscs, value.user_id);
|
||||||
|
if value.options.is_some() {
|
||||||
|
cdd.with_options(serde_json::to_value(value.options).unwrap())
|
||||||
|
} else {
|
||||||
|
cdd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 用户的草稿数据查询条件
|
/// 用户的草稿数据查询条件
|
||||||
#[derive(Debug, InputObject)]
|
#[derive(Debug, InputObject)]
|
||||||
pub struct UserDraftDataFilterDto {
|
#[graphql(concrete(name = "UserDraftIscsDataFilterDto", params(IscsDataOptions)))]
|
||||||
|
pub struct UserDraftDataFilterDto<T: DataOptions> {
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub data_type: Option<rtss_dto::common::DataType>,
|
pub data_type: Option<rtss_dto::common::DataType>,
|
||||||
|
pub options: Option<T>,
|
||||||
pub is_shared: Option<bool>,
|
pub is_shared: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<UserDraftDataFilterDto> for rtss_db::DraftDataQuery {
|
impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtss_db::DraftDataQuery {
|
||||||
fn from(value: UserDraftDataFilterDto) -> Self {
|
fn from(value: UserDraftDataFilterDto<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
user_id: Some(value.user_id),
|
user_id: Some(value.user_id),
|
||||||
name: value.name,
|
name: value.name,
|
||||||
data_type: value.data_type,
|
data_type: value.data_type,
|
||||||
|
options_filter: value.options.map(|o| o.to_data_options_filter_clause()),
|
||||||
is_shared: value.is_shared,
|
is_shared: value.is_shared,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)]
|
||||||
pub struct SharedDraftDataFilterDto {
|
#[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))]
|
||||||
|
|
||||||
|
pub struct SharedDraftDataFilterDto<T: DataOptions> {
|
||||||
pub user_id: Option<i32>,
|
pub user_id: Option<i32>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub data_type: Option<rtss_dto::common::DataType>,
|
pub data_type: Option<rtss_dto::common::DataType>,
|
||||||
|
pub options: Option<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SharedDraftDataFilterDto> for rtss_db::DraftDataQuery {
|
impl<T: DataOptions> From<SharedDraftDataFilterDto<T>> for rtss_db::DraftDataQuery {
|
||||||
fn from(value: SharedDraftDataFilterDto) -> Self {
|
fn from(value: SharedDraftDataFilterDto<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
user_id: value.user_id,
|
user_id: value.user_id,
|
||||||
name: value.name,
|
name: value.name,
|
||||||
data_type: value.data_type,
|
data_type: value.data_type,
|
||||||
is_shared: Some(true),
|
is_shared: Some(true),
|
||||||
|
options_filter: value.options.map(|o| o.to_data_options_filter_clause()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,15 +267,17 @@ impl From<DraftDataFilterDto> for rtss_db::DraftDataQuery {
|
|||||||
name: value.name,
|
name: value.name,
|
||||||
data_type: value.data_type,
|
data_type: value.data_type,
|
||||||
is_shared: value.is_shared,
|
is_shared: value.is_shared,
|
||||||
|
options_filter: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, SimpleObject)]
|
#[derive(Debug, SimpleObject)]
|
||||||
pub struct DraftData {
|
pub struct DraftDataWithStringOptions {
|
||||||
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<String>,
|
||||||
pub data: Option<Vec<u8>>,
|
pub data: Option<Vec<u8>>,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub is_shared: bool,
|
pub is_shared: bool,
|
||||||
@ -241,12 +285,43 @@ pub struct DraftData {
|
|||||||
pub updated_at: DateTime<Local>,
|
pub updated_at: DateTime<Local>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<rtss_db::model::DraftDataModel> for DraftData {
|
impl From<rtss_db::model::DraftDataModel> for DraftDataWithStringOptions {
|
||||||
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.map(|o| serde_json::to_string(&o).unwrap()),
|
||||||
|
data: value.data,
|
||||||
|
user_id: value.user_id,
|
||||||
|
is_shared: value.is_shared,
|
||||||
|
created_at: value.created_at,
|
||||||
|
updated_at: value.updated_at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, SimpleObject)]
|
||||||
|
#[graphql(concrete(name = "DraftIscsData", params(IscsDataOptions)))]
|
||||||
|
pub struct DraftData<T: OutputType> {
|
||||||
|
pub id: i32,
|
||||||
|
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: DateTime<Local>,
|
||||||
|
pub updated_at: DateTime<Local>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: DataOptions> From<rtss_db::model::DraftDataModel> for DraftData<T> {
|
||||||
|
fn from(value: rtss_db::model::DraftDataModel) -> Self {
|
||||||
|
Self {
|
||||||
|
id: value.id,
|
||||||
|
name: value.name,
|
||||||
|
data_type: DataType::try_from(value.data_type).unwrap(),
|
||||||
|
options: value.options.map(|o| serde_json::from_value(o).unwrap()),
|
||||||
data: value.data,
|
data: value.data,
|
||||||
user_id: value.user_id,
|
user_id: value.user_id,
|
||||||
is_shared: value.is_shared,
|
is_shared: value.is_shared,
|
||||||
@ -259,7 +334,7 @@ impl From<rtss_db::model::DraftDataModel> for DraftData {
|
|||||||
#[derive(Debug, SimpleObject)]
|
#[derive(Debug, SimpleObject)]
|
||||||
pub struct DraftDataPage {
|
pub struct DraftDataPage {
|
||||||
pub total: i64,
|
pub total: i64,
|
||||||
pub data: Vec<DraftData>,
|
pub data: Vec<DraftDataWithStringOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<rtss_db::common::PageResult<rtss_db::model::DraftDataModel>> for DraftDataPage {
|
impl From<rtss_db::common::PageResult<rtss_db::model::DraftDataModel>> for DraftDataPage {
|
||||||
@ -270,3 +345,47 @@ impl From<rtss_db::common::PageResult<rtss_db::model::DraftDataModel>> for Draft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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"}'"#);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,6 +5,8 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
sqlx = { workspace = true, features = [
|
sqlx = { workspace = true, features = [
|
||||||
"runtime-tokio",
|
"runtime-tokio",
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -2,6 +2,7 @@ use std::vec;
|
|||||||
|
|
||||||
use rtss_dto::common::DataType;
|
use rtss_dto::common::DataType;
|
||||||
use rtss_log::tracing::debug;
|
use rtss_log::tracing::debug;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{PageQuery, PageResult, Sort, SortOrder, TableColumn},
|
common::{PageQuery, PageResult, Sort, SortOrder, TableColumn},
|
||||||
@ -69,6 +70,8 @@ pub struct DraftDataQuery {
|
|||||||
pub user_id: Option<i32>,
|
pub user_id: Option<i32>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub data_type: Option<DataType>,
|
pub data_type: Option<DataType>,
|
||||||
|
/// 选项过滤条件,由业务层构建并确保合法性
|
||||||
|
pub options_filter: Option<String>,
|
||||||
pub is_shared: Option<bool>,
|
pub is_shared: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +100,11 @@ impl DraftDataQuery {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_options_filter(mut self, options_filter: &str) -> Self {
|
||||||
|
self.options_filter = Some(options_filter.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn build_filter(&self) -> String {
|
fn build_filter(&self) -> String {
|
||||||
let mut filters = vec![];
|
let mut filters = vec![];
|
||||||
if let Some(user_id) = self.user_id {
|
if let Some(user_id) = self.user_id {
|
||||||
@ -123,6 +131,9 @@ impl DraftDataQuery {
|
|||||||
is_shared
|
is_shared
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let Some(options_filter) = &self.options_filter {
|
||||||
|
filters.push(options_filter.clone());
|
||||||
|
}
|
||||||
if filters.is_empty() {
|
if filters.is_empty() {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
@ -134,6 +145,7 @@ impl DraftDataQuery {
|
|||||||
pub struct CreateDraftData {
|
pub struct CreateDraftData {
|
||||||
name: String,
|
name: String,
|
||||||
data_type: DataType,
|
data_type: DataType,
|
||||||
|
options: Option<Value>,
|
||||||
data: Option<Vec<u8>>,
|
data: Option<Vec<u8>>,
|
||||||
default_release_data_id: Option<i32>,
|
default_release_data_id: Option<i32>,
|
||||||
user_id: i32,
|
user_id: i32,
|
||||||
@ -144,12 +156,18 @@ impl CreateDraftData {
|
|||||||
CreateDraftData {
|
CreateDraftData {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
data_type,
|
data_type,
|
||||||
|
options: None,
|
||||||
data: None,
|
data: None,
|
||||||
default_release_data_id: None,
|
default_release_data_id: None,
|
||||||
user_id,
|
user_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_options(mut self, options: Value) -> Self {
|
||||||
|
self.options = Some(options);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_data(mut self, data: &[u8]) -> Self {
|
pub fn with_data(mut self, data: &[u8]) -> Self {
|
||||||
self.data = Some(data.to_vec());
|
self.data = Some(data.to_vec());
|
||||||
self
|
self
|
||||||
@ -240,21 +258,23 @@ impl DraftDataAccessor for RtssDbAccessor {
|
|||||||
// 插入数据
|
// 插入数据
|
||||||
let table = DraftDataColumn::Table.name();
|
let table = DraftDataColumn::Table.name();
|
||||||
let columns = format!(
|
let columns = format!(
|
||||||
"{}, {}, {}, {}, {}",
|
"{}, {}, {}, {}, {}, {}",
|
||||||
DraftDataColumn::Name.name(),
|
DraftDataColumn::Name.name(),
|
||||||
DraftDataColumn::DataType.name(),
|
DraftDataColumn::DataType.name(),
|
||||||
|
DraftDataColumn::Options.name(),
|
||||||
DraftDataColumn::UserId.name(),
|
DraftDataColumn::UserId.name(),
|
||||||
DraftDataColumn::Data.name(),
|
DraftDataColumn::Data.name(),
|
||||||
DraftDataColumn::DefaultReleaseDataId.name(),
|
DraftDataColumn::DefaultReleaseDataId.name(),
|
||||||
);
|
);
|
||||||
let sql =
|
let sql =
|
||||||
format!("INSERT INTO {table} ({columns}) VALUES ($1, $2, $3, $4, $5) RETURNING *",);
|
format!("INSERT INTO {table} ({columns}) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *",);
|
||||||
// log sql
|
// log sql
|
||||||
debug!("create sql: {}", sql);
|
debug!("create sql: {}", sql);
|
||||||
// 插入数据
|
// 插入数据
|
||||||
let draft_data: DraftDataModel = sqlx::query_as(&sql)
|
let draft_data: DraftDataModel = sqlx::query_as(&sql)
|
||||||
.bind(create.name)
|
.bind(create.name)
|
||||||
.bind(create.data_type as i32)
|
.bind(create.data_type as i32)
|
||||||
|
.bind(create.options)
|
||||||
.bind(create.user_id)
|
.bind(create.user_id)
|
||||||
.bind(create.data)
|
.bind(create.data)
|
||||||
.bind(create.default_release_data_id)
|
.bind(create.default_release_data_id)
|
||||||
@ -380,9 +400,16 @@ impl DraftDataAccessor for RtssDbAccessor {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
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;
|
||||||
|
|
||||||
|
#[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 basic_use_test(pool: PgPool) -> Result<(), DbAccessError> {
|
async fn basic_use_test(pool: PgPool) -> Result<(), DbAccessError> {
|
||||||
@ -455,15 +482,7 @@ mod tests {
|
|||||||
|
|
||||||
// 查询确认当前数据已删除
|
// 查询确认当前数据已删除
|
||||||
let page = accessor
|
let page = accessor
|
||||||
.query_draft_data(
|
.query_draft_data(DraftDataQuery::new(), PageQuery::new(1, 100))
|
||||||
DraftDataQuery {
|
|
||||||
user_id: None,
|
|
||||||
name: None,
|
|
||||||
data_type: None,
|
|
||||||
is_shared: None,
|
|
||||||
},
|
|
||||||
PageQuery::new(1, 100),
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(page.total, 0);
|
assert_eq!(page.total, 0);
|
||||||
|
|
||||||
@ -471,11 +490,28 @@ mod tests {
|
|||||||
// 分四个user_id各插入5条数据
|
// 分四个user_id各插入5条数据
|
||||||
for i in 1..5 {
|
for i in 1..5 {
|
||||||
for j in 1..6 {
|
for j in 1..6 {
|
||||||
let draft = accessor
|
|
||||||
.create_draft_data(CreateDraftData::new(&format!("test{}", j), DataType::Em, i))
|
|
||||||
.await?;
|
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
|
let draft = accessor
|
||||||
|
.create_draft_data(
|
||||||
|
CreateDraftData::new(&format!("test{}", j), DataType::Iscs, i)
|
||||||
|
.with_options(
|
||||||
|
serde_json::to_value(IscsDataOptions {
|
||||||
|
style: IscsStyle::DaShiZhiNeng,
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
println!("{:?}", draft);
|
||||||
accessor.set_draft_data_shared(draft.id, true).await?;
|
accessor.set_draft_data_shared(draft.id, true).await?;
|
||||||
|
} else {
|
||||||
|
accessor
|
||||||
|
.create_draft_data(CreateDraftData::new(
|
||||||
|
&format!("test{}", j),
|
||||||
|
DataType::Em,
|
||||||
|
i,
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +519,7 @@ mod tests {
|
|||||||
let page = accessor
|
let page = accessor
|
||||||
.query_draft_data(
|
.query_draft_data(
|
||||||
DraftDataQuery::new()
|
DraftDataQuery::new()
|
||||||
.with_user_id(1)
|
.with_user_id(2)
|
||||||
.with_name("test".to_string())
|
.with_name("test".to_string())
|
||||||
.with_data_type(DataType::Em),
|
.with_data_type(DataType::Em),
|
||||||
PageQuery::new(1, 10),
|
PageQuery::new(1, 10),
|
||||||
@ -505,6 +541,16 @@ mod tests {
|
|||||||
.await?;
|
.await?;
|
||||||
assert_eq!(page.total, 5);
|
assert_eq!(page.total, 5);
|
||||||
|
|
||||||
|
// 查询options
|
||||||
|
let page = accessor
|
||||||
|
.query_draft_data(
|
||||||
|
DraftDataQuery::new()
|
||||||
|
.with_options_filter(r#"options @> '{"style":"DaShiZhiNeng"}'"#),
|
||||||
|
PageQuery::new(1, 10),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
assert_eq!(page.total, 5);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
|
use serde_json::Value;
|
||||||
use sqlx::types::chrono::{DateTime, Local};
|
use sqlx::types::chrono::{DateTime, Local};
|
||||||
|
|
||||||
use crate::common::TableColumn;
|
use crate::common::TableColumn;
|
||||||
|
|
||||||
/// 数据库表 rtss.draft_data 列映射
|
/// 数据库表 rtss.draft_data 列映射
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum DraftDataColumn {
|
pub enum DraftDataColumn {
|
||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
Name,
|
Name,
|
||||||
DataType,
|
DataType,
|
||||||
|
Options,
|
||||||
Data,
|
Data,
|
||||||
DefaultReleaseDataId,
|
DefaultReleaseDataId,
|
||||||
UserId,
|
UserId,
|
||||||
@ -23,6 +25,8 @@ pub struct DraftDataModel {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub data_type: i32,
|
pub data_type: i32,
|
||||||
#[sqlx(default)]
|
#[sqlx(default)]
|
||||||
|
pub options: Option<Value>,
|
||||||
|
#[sqlx(default)]
|
||||||
pub data: Option<Vec<u8>>,
|
pub data: Option<Vec<u8>>,
|
||||||
#[sqlx(default)]
|
#[sqlx(default)]
|
||||||
pub default_release_data_id: Option<i32>,
|
pub default_release_data_id: Option<i32>,
|
||||||
@ -35,11 +39,12 @@ pub struct DraftDataModel {
|
|||||||
|
|
||||||
/// 数据库表 rtss.release_data 列映射
|
/// 数据库表 rtss.release_data 列映射
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum ReleaseDataColumn {
|
pub enum ReleaseDataColumn {
|
||||||
Table,
|
Table,
|
||||||
Id,
|
Id,
|
||||||
Name,
|
Name,
|
||||||
DataType,
|
DataType,
|
||||||
|
Options,
|
||||||
UsedVersionId,
|
UsedVersionId,
|
||||||
UserId,
|
UserId,
|
||||||
IsPublished,
|
IsPublished,
|
||||||
@ -53,6 +58,8 @@ pub struct ReleaseDataModel {
|
|||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub data_type: i32,
|
pub data_type: i32,
|
||||||
|
#[sqlx(default)]
|
||||||
|
pub options: Option<Value>,
|
||||||
pub used_version_id: Option<i32>,
|
pub used_version_id: Option<i32>,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub is_published: bool,
|
pub is_published: bool,
|
||||||
@ -201,6 +208,7 @@ impl TableColumn for DraftDataColumn {
|
|||||||
DraftDataColumn::Id => "id",
|
DraftDataColumn::Id => "id",
|
||||||
DraftDataColumn::Name => "name",
|
DraftDataColumn::Name => "name",
|
||||||
DraftDataColumn::DataType => "data_type",
|
DraftDataColumn::DataType => "data_type",
|
||||||
|
DraftDataColumn::Options => "options",
|
||||||
DraftDataColumn::Data => "data",
|
DraftDataColumn::Data => "data",
|
||||||
DraftDataColumn::DefaultReleaseDataId => "default_release_data_id",
|
DraftDataColumn::DefaultReleaseDataId => "default_release_data_id",
|
||||||
DraftDataColumn::UserId => "user_id",
|
DraftDataColumn::UserId => "user_id",
|
||||||
@ -218,6 +226,7 @@ impl TableColumn for ReleaseDataColumn {
|
|||||||
ReleaseDataColumn::Id => "id",
|
ReleaseDataColumn::Id => "id",
|
||||||
ReleaseDataColumn::Name => "name",
|
ReleaseDataColumn::Name => "name",
|
||||||
ReleaseDataColumn::DataType => "data_type",
|
ReleaseDataColumn::DataType => "data_type",
|
||||||
|
ReleaseDataColumn::Options => "options",
|
||||||
ReleaseDataColumn::UsedVersionId => "used_version_id",
|
ReleaseDataColumn::UsedVersionId => "used_version_id",
|
||||||
ReleaseDataColumn::UserId => "user_id",
|
ReleaseDataColumn::UserId => "user_id",
|
||||||
ReleaseDataColumn::IsPublished => "is_published",
|
ReleaseDataColumn::IsPublished => "is_published",
|
||||||
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
prost = "0.13"
|
prost = "0.13"
|
||||||
async-graphql = { version = "7.0.7", features = ["chrono"] }
|
async-graphql = { version = "7.0.7", features = ["chrono"] }
|
||||||
sqlx = { workspace = true }
|
sqlx = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
prost-build = "0.13"
|
prost-build = "0.13"
|
||||||
|
@ -23,6 +23,11 @@ fn main() {
|
|||||||
.out_dir("src/pb")
|
.out_dir("src/pb")
|
||||||
.type_attribute("common.DataType", "#[derive(sqlx::Type)]")
|
.type_attribute("common.DataType", "#[derive(sqlx::Type)]")
|
||||||
.type_attribute("common.DataType", "#[derive(async_graphql::Enum)]")
|
.type_attribute("common.DataType", "#[derive(async_graphql::Enum)]")
|
||||||
|
.type_attribute("common.IscsStyle", "#[derive(async_graphql::Enum)]")
|
||||||
|
.type_attribute(
|
||||||
|
"common.IscsStyle",
|
||||||
|
"#[derive(serde::Serialize, serde::Deserialize)]",
|
||||||
|
)
|
||||||
.type_attribute("common.FeatureType", "#[derive(sqlx::Type)]")
|
.type_attribute("common.FeatureType", "#[derive(sqlx::Type)]")
|
||||||
.compile_protos(
|
.compile_protos(
|
||||||
&[
|
&[
|
||||||
|
@ -141,6 +141,47 @@ impl DataType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(
|
||||||
|
async_graphql::Enum,
|
||||||
|
serde::Serialize,
|
||||||
|
serde::Deserialize,
|
||||||
|
Clone,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
::prost::Enumeration,
|
||||||
|
)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum IscsStyle {
|
||||||
|
/// 未知
|
||||||
|
Unknown = 0,
|
||||||
|
/// 达实智能(福州一号线)
|
||||||
|
DaShiZhiNeng = 1,
|
||||||
|
}
|
||||||
|
impl IscsStyle {
|
||||||
|
/// 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 {
|
||||||
|
IscsStyle::Unknown => "IscsStyle_Unknown",
|
||||||
|
IscsStyle::DaShiZhiNeng => "DaShiZhiNeng",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
|
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||||
|
match value {
|
||||||
|
"IscsStyle_Unknown" => Some(Self::Unknown),
|
||||||
|
"DaShiZhiNeng" => Some(Self::DaShiZhiNeng),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// 功能特性类型
|
/// 功能特性类型
|
||||||
#[derive(
|
#[derive(
|
||||||
sqlx::Type, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration,
|
sqlx::Type, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration,
|
||||||
|
@ -7,6 +7,7 @@ CREATE TABLE
|
|||||||
id SERIAL PRIMARY KEY, -- id 自增主键
|
id SERIAL PRIMARY KEY, -- id 自增主键
|
||||||
name VARCHAR(128) NOT NULL, -- 草稿名称
|
name VARCHAR(128) NOT NULL, -- 草稿名称
|
||||||
data_type INT NOT NULL, -- 数据类型
|
data_type INT NOT NULL, -- 数据类型
|
||||||
|
options JSONB NULL, -- 数据相关的参数项或配置项
|
||||||
data BYTEA, -- 草稿数据
|
data BYTEA, -- 草稿数据
|
||||||
default_release_data_id INT NULL, -- 默认发布数据id
|
default_release_data_id INT NULL, -- 默认发布数据id
|
||||||
user_id INT NOT NULL, -- 创建用户id
|
user_id INT NOT NULL, -- 创建用户id
|
||||||
@ -22,6 +23,9 @@ CREATE INDEX ON rtss.draft_data (user_id);
|
|||||||
-- 创建草稿数据类型索引
|
-- 创建草稿数据类型索引
|
||||||
CREATE INDEX ON rtss.draft_data (data_type);
|
CREATE INDEX ON rtss.draft_data (data_type);
|
||||||
|
|
||||||
|
-- 创建草稿数据配置项索引
|
||||||
|
CREATE INDEX ON rtss.draft_data USING GIN (options);
|
||||||
|
|
||||||
-- 注释草稿数据表
|
-- 注释草稿数据表
|
||||||
COMMENT ON TABLE rtss.draft_data IS '草稿数据表';
|
COMMENT ON TABLE rtss.draft_data IS '草稿数据表';
|
||||||
|
|
||||||
@ -32,6 +36,8 @@ COMMENT ON COLUMN rtss.draft_data.name IS '草稿名称';
|
|||||||
|
|
||||||
COMMENT ON COLUMN rtss.draft_data.data_type IS '数据类型';
|
COMMENT ON COLUMN rtss.draft_data.data_type IS '数据类型';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN rtss.draft_data.options IS '数据相关的参数项或配置项';
|
||||||
|
|
||||||
COMMENT ON COLUMN rtss.draft_data.data IS '草稿数据';
|
COMMENT ON COLUMN rtss.draft_data.data IS '草稿数据';
|
||||||
|
|
||||||
COMMENT ON COLUMN rtss.draft_data.user_id IS '创建用户id';
|
COMMENT ON COLUMN rtss.draft_data.user_id IS '创建用户id';
|
||||||
@ -48,6 +54,7 @@ CREATE TABLE
|
|||||||
id SERIAL PRIMARY KEY, -- id 自增主键
|
id SERIAL PRIMARY KEY, -- id 自增主键
|
||||||
name VARCHAR(128) NOT NULL UNIQUE, -- 发布数据名称(数据唯一标识)
|
name VARCHAR(128) NOT NULL UNIQUE, -- 发布数据名称(数据唯一标识)
|
||||||
data_type INT NOT NULL, -- 数据类型
|
data_type INT NOT NULL, -- 数据类型
|
||||||
|
options JSONB NULL, -- 数据相关的参数项或配置项
|
||||||
used_version_id INT NULL, -- 使用的版本数据id
|
used_version_id INT NULL, -- 使用的版本数据id
|
||||||
user_id INT NOT NULL, -- 发布/更新用户id
|
user_id INT NOT NULL, -- 发布/更新用户id
|
||||||
is_published BOOLEAN NOT NULL DEFAULT TRUE, -- 是否上架
|
is_published BOOLEAN NOT NULL DEFAULT TRUE, -- 是否上架
|
||||||
@ -65,6 +72,8 @@ COMMENT ON COLUMN rtss.release_data.name IS '发布数据名称(数据唯一标
|
|||||||
|
|
||||||
COMMENT ON COLUMN rtss.release_data.data_type IS '数据类型';
|
COMMENT ON COLUMN rtss.release_data.data_type IS '数据类型';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN rtss.release_data.options IS '数据相关的参数项或配置项';
|
||||||
|
|
||||||
COMMENT ON COLUMN rtss.release_data.used_version_id IS '使用的版本数据id';
|
COMMENT ON COLUMN rtss.release_data.used_version_id IS '使用的版本数据id';
|
||||||
|
|
||||||
COMMENT ON COLUMN rtss.release_data.user_id IS '发布/更新用户id';
|
COMMENT ON COLUMN rtss.release_data.user_id IS '发布/更新用户id';
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 4e447beffa31c94b30bcee57a7cf229dcf01351f
|
Subproject commit a1622410919b58683bc0ec059b4f5de575583c13
|
Loading…
Reference in New Issue
Block a user