草稿和发布数据添加options配置项
All checks were successful
build / build-rust (push) Successful in 3m0s

实现配置项相关的CRUD
调整草稿数据管理接口
This commit is contained in:
soul-walker 2024-09-19 00:07:53 +08:00
parent 875788a71d
commit 2a7a2ffc99
13 changed files with 289 additions and 52 deletions

View File

@ -11,6 +11,7 @@
"Joylink",
"jsonwebtoken",
"mplj",
"Neng",
"plpgsql",
"prost",
"proto",

3
Cargo.lock generated
View File

@ -2199,6 +2199,8 @@ dependencies = [
"anyhow",
"rtss_dto",
"rtss_log",
"serde",
"serde_json",
"sqlx",
"thiserror",
]
@ -2210,6 +2212,7 @@ dependencies = [
"async-graphql",
"prost",
"prost-build",
"serde",
"sqlx",
]

View File

@ -23,6 +23,7 @@ sqlx = { version = "0.8", features = [
"chrono",
] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.125"
anyhow = "1.0"
[dependencies]

View File

@ -6,8 +6,8 @@ edition = "2021"
[dependencies]
anyhow = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"
serde = { workspace = true }
serde_json = { workspace = true }
chrono = { version = "0.4.38", features = ["serde"] }
axum = "0.7.5"
axum-extra = { version = "0.9.3", features = ["typed-header"] }

View File

@ -1,8 +1,13 @@
use async_graphql::{Context, InputObject, Object, SimpleObject};
use async_graphql::{InputType, OutputType};
use chrono::{DateTime, Local};
use rtss_db::common::TableColumn;
use rtss_db::model::DraftDataColumn;
use rtss_db::DraftDataAccessor;
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;
@ -28,12 +33,12 @@ impl DraftDataQuery {
Ok(paging_result.into())
}
/// 分页查询用户的草稿数据
async fn user_draft_data_paging<'ctx>(
async fn user_draft_iscs_data_paging<'ctx>(
&self,
ctx: &Context<'ctx>,
paging: PageQueryDto,
query: UserDraftDataFilterDto,
) -> async_graphql::Result<DraftDataPage> {
query: UserDraftDataFilterDto<IscsDataOptions>,
) -> async_graphql::Result<DraftIscsDataPage> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging_result = db_accessor
.query_draft_data(query.into(), paging.into())
@ -41,12 +46,12 @@ impl DraftDataQuery {
Ok(paging_result.into())
}
/// 分页查询共享的草稿数据
async fn shared_draft_data_paging<'ctx>(
async fn shared_draft_iscs_data_paging<'ctx>(
&self,
ctx: &Context<'ctx>,
paging: PageQueryDto,
query: SharedDraftDataFilterDto,
) -> async_graphql::Result<DraftDataPage> {
query: SharedDraftDataFilterDto<IscsDataOptions>,
) -> async_graphql::Result<DraftIscsDataPage> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let paging_result = db_accessor
.query_draft_data(query.into(), paging.into())
@ -54,7 +59,11 @@ impl DraftDataQuery {
Ok(paging_result.into())
}
/// 根据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 draft_data = db_accessor.query_draft_data_by_id(id).await?;
Ok(draft_data.into())
@ -74,12 +83,12 @@ impl DraftDataQuery {
#[Object]
impl DraftDataMutation {
/// 创建草稿数据
async fn create_draft_data(
/// 创建草稿ISCS数据
async fn create_draft_iscs_data(
&self,
ctx: &Context<'_>,
input: CreateDraftDataDto,
) -> async_graphql::Result<DraftData> {
input: CreateDraftDataDto<IscsDataOptions>,
) -> async_graphql::Result<DraftData<IscsDataOptions>> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.create_draft_data(input.into()).await?;
Ok(draft_data.into())
@ -90,7 +99,7 @@ impl DraftDataMutation {
ctx: &Context<'_>,
id: i32,
name: String,
) -> async_graphql::Result<DraftData> {
) -> async_graphql::Result<DraftDataWithStringOptions> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.update_draft_data_name(id, &name).await?;
Ok(draft_data.into())
@ -101,7 +110,7 @@ impl DraftDataMutation {
ctx: &Context<'_>,
id: i32,
data: Vec<u8>,
) -> async_graphql::Result<DraftData> {
) -> async_graphql::Result<DraftDataWithStringOptions> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor
.update_draft_data_data(id, data.as_slice())
@ -114,7 +123,7 @@ impl DraftDataMutation {
ctx: &Context<'_>,
id: i32,
is_shared: bool,
) -> async_graphql::Result<DraftData> {
) -> async_graphql::Result<DraftDataWithStringOptions> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.set_draft_data_shared(id, is_shared).await?;
Ok(draft_data.into())
@ -135,7 +144,7 @@ impl DraftDataMutation {
ctx: &Context<'_>,
id: i32,
release_data_id: i32,
) -> async_graphql::Result<DraftData> {
) -> async_graphql::Result<DraftDataWithStringOptions> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor
.set_default_release_data_id(id, release_data_id)
@ -149,7 +158,7 @@ impl DraftDataMutation {
id: i32,
name: String,
user_id: i32,
) -> async_graphql::Result<DraftData> {
) -> async_graphql::Result<DraftDataWithStringOptions> {
let db_accessor = ctx.data::<RtssDbAccessor>()?;
let draft_data = db_accessor.save_as_new_draft(id, &name, user_id).await?;
Ok(draft_data.into())
@ -157,54 +166,87 @@ impl DraftDataMutation {
}
#[derive(Debug, InputObject)]
pub struct CreateDraftDataDto {
#[graphql(concrete(name = "CreateDraftIscsDto", params(IscsDataOptions)))]
pub struct CreateDraftDataDto<T: DataOptions> {
pub name: String,
pub data_type: rtss_dto::common::DataType,
pub data: Vec<u8>,
pub options: Option<T>,
pub user_id: i32,
}
impl From<CreateDraftDataDto> for rtss_db::CreateDraftData {
fn from(value: CreateDraftDataDto) -> Self {
Self::new(&value.name, value.data_type, value.user_id).with_data(value.data.as_slice())
impl<T: DataOptions> From<CreateDraftDataDto<T>> for rtss_db::CreateDraftData {
fn from(value: CreateDraftDataDto<T>) -> Self {
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)]
pub struct UserDraftDataFilterDto {
#[graphql(concrete(name = "UserDraftIscsDataFilterDto", params(IscsDataOptions)))]
pub struct UserDraftDataFilterDto<T: DataOptions> {
pub user_id: i32,
pub name: Option<String>,
pub data_type: Option<rtss_dto::common::DataType>,
pub options: Option<T>,
pub is_shared: Option<bool>,
}
impl From<UserDraftDataFilterDto> for rtss_db::DraftDataQuery {
fn from(value: UserDraftDataFilterDto) -> Self {
impl<T: DataOptions> From<UserDraftDataFilterDto<T>> for rtss_db::DraftDataQuery {
fn from(value: UserDraftDataFilterDto<T>) -> Self {
Self {
user_id: Some(value.user_id),
name: value.name,
data_type: value.data_type,
options_filter: value.options.map(|o| o.to_data_options_filter_clause()),
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)]
pub struct SharedDraftDataFilterDto {
#[graphql(concrete(name = "SharedDraftIscsDataFilterDto", params(IscsDataOptions)))]
pub struct SharedDraftDataFilterDto<T: DataOptions> {
pub user_id: Option<i32>,
pub name: Option<String>,
pub data_type: Option<rtss_dto::common::DataType>,
pub options: Option<T>,
}
impl From<SharedDraftDataFilterDto> for rtss_db::DraftDataQuery {
fn from(value: SharedDraftDataFilterDto) -> Self {
impl<T: DataOptions> From<SharedDraftDataFilterDto<T>> for rtss_db::DraftDataQuery {
fn from(value: SharedDraftDataFilterDto<T>) -> Self {
Self {
user_id: value.user_id,
name: value.name,
data_type: value.data_type,
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,
data_type: value.data_type,
is_shared: value.is_shared,
options_filter: None,
}
}
}
#[derive(Debug, SimpleObject)]
pub struct DraftData {
pub struct DraftDataWithStringOptions {
pub id: i32,
pub name: String,
pub data_type: rtss_dto::common::DataType,
pub options: Option<String>,
pub data: Option<Vec<u8>>,
pub user_id: i32,
pub is_shared: bool,
@ -241,12 +285,43 @@ pub struct DraftData {
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 {
Self {
id: value.id,
name: value.name,
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,
user_id: value.user_id,
is_shared: value.is_shared,
@ -259,7 +334,7 @@ impl From<rtss_db::model::DraftDataModel> for DraftData {
#[derive(Debug, SimpleObject)]
pub struct DraftDataPage {
pub total: i64,
pub data: Vec<DraftData>,
pub data: Vec<DraftDataWithStringOptions>,
}
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"}'"#);
}
}

View File

@ -5,6 +5,8 @@ edition = "2021"
[dependencies]
anyhow = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
sqlx = { workspace = true, features = [
"runtime-tokio",
"macros",

View File

@ -2,6 +2,7 @@ use std::vec;
use rtss_dto::common::DataType;
use rtss_log::tracing::debug;
use serde_json::Value;
use crate::{
common::{PageQuery, PageResult, Sort, SortOrder, TableColumn},
@ -69,6 +70,8 @@ pub struct DraftDataQuery {
pub user_id: Option<i32>,
pub name: Option<String>,
pub data_type: Option<DataType>,
/// 选项过滤条件,由业务层构建并确保合法性
pub options_filter: Option<String>,
pub is_shared: Option<bool>,
}
@ -97,6 +100,11 @@ impl DraftDataQuery {
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 {
let mut filters = vec![];
if let Some(user_id) = self.user_id {
@ -123,6 +131,9 @@ impl DraftDataQuery {
is_shared
));
}
if let Some(options_filter) = &self.options_filter {
filters.push(options_filter.clone());
}
if filters.is_empty() {
"".to_string()
} else {
@ -134,6 +145,7 @@ impl DraftDataQuery {
pub struct CreateDraftData {
name: String,
data_type: DataType,
options: Option<Value>,
data: Option<Vec<u8>>,
default_release_data_id: Option<i32>,
user_id: i32,
@ -144,12 +156,18 @@ impl CreateDraftData {
CreateDraftData {
name: name.to_string(),
data_type,
options: None,
data: None,
default_release_data_id: None,
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 {
self.data = Some(data.to_vec());
self
@ -240,21 +258,23 @@ impl DraftDataAccessor for RtssDbAccessor {
// 插入数据
let table = DraftDataColumn::Table.name();
let columns = format!(
"{}, {}, {}, {}, {}",
"{}, {}, {}, {}, {}, {}",
DraftDataColumn::Name.name(),
DraftDataColumn::DataType.name(),
DraftDataColumn::Options.name(),
DraftDataColumn::UserId.name(),
DraftDataColumn::Data.name(),
DraftDataColumn::DefaultReleaseDataId.name(),
);
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
debug!("create sql: {}", sql);
// 插入数据
let draft_data: DraftDataModel = sqlx::query_as(&sql)
.bind(create.name)
.bind(create.data_type as i32)
.bind(create.options)
.bind(create.user_id)
.bind(create.data)
.bind(create.default_release_data_id)
@ -380,9 +400,16 @@ impl DraftDataAccessor for RtssDbAccessor {
#[cfg(test)]
mod tests {
use super::*;
use rtss_dto::common::IscsStyle;
use rtss_log::tracing::Level;
use serde::{Deserialize, Serialize};
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.
#[sqlx::test(migrator = "crate::MIGRATOR")]
async fn basic_use_test(pool: PgPool) -> Result<(), DbAccessError> {
@ -455,15 +482,7 @@ mod tests {
// 查询确认当前数据已删除
let page = accessor
.query_draft_data(
DraftDataQuery {
user_id: None,
name: None,
data_type: None,
is_shared: None,
},
PageQuery::new(1, 100),
)
.query_draft_data(DraftDataQuery::new(), PageQuery::new(1, 100))
.await?;
assert_eq!(page.total, 0);
@ -471,11 +490,28 @@ mod tests {
// 分四个user_id各插入5条数据
for i in 1..5 {
for j in 1..6 {
let draft = accessor
.create_draft_data(CreateDraftData::new(&format!("test{}", j), DataType::Em, i))
.await?;
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?;
} else {
accessor
.create_draft_data(CreateDraftData::new(
&format!("test{}", j),
DataType::Em,
i,
))
.await?;
}
}
}
@ -483,7 +519,7 @@ mod tests {
let page = accessor
.query_draft_data(
DraftDataQuery::new()
.with_user_id(1)
.with_user_id(2)
.with_name("test".to_string())
.with_data_type(DataType::Em),
PageQuery::new(1, 10),
@ -505,6 +541,16 @@ mod tests {
.await?;
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(())
}
}

View File

@ -1,14 +1,16 @@
use serde_json::Value;
use sqlx::types::chrono::{DateTime, Local};
use crate::common::TableColumn;
/// 数据库表 rtss.draft_data 列映射
#[derive(Debug)]
pub(crate) enum DraftDataColumn {
pub enum DraftDataColumn {
Table,
Id,
Name,
DataType,
Options,
Data,
DefaultReleaseDataId,
UserId,
@ -23,6 +25,8 @@ pub struct DraftDataModel {
pub name: String,
pub data_type: i32,
#[sqlx(default)]
pub options: Option<Value>,
#[sqlx(default)]
pub data: Option<Vec<u8>>,
#[sqlx(default)]
pub default_release_data_id: Option<i32>,
@ -35,11 +39,12 @@ pub struct DraftDataModel {
/// 数据库表 rtss.release_data 列映射
#[derive(Debug)]
pub(crate) enum ReleaseDataColumn {
pub enum ReleaseDataColumn {
Table,
Id,
Name,
DataType,
Options,
UsedVersionId,
UserId,
IsPublished,
@ -53,6 +58,8 @@ pub struct ReleaseDataModel {
pub id: i32,
pub name: String,
pub data_type: i32,
#[sqlx(default)]
pub options: Option<Value>,
pub used_version_id: Option<i32>,
pub user_id: i32,
pub is_published: bool,
@ -201,6 +208,7 @@ impl TableColumn for DraftDataColumn {
DraftDataColumn::Id => "id",
DraftDataColumn::Name => "name",
DraftDataColumn::DataType => "data_type",
DraftDataColumn::Options => "options",
DraftDataColumn::Data => "data",
DraftDataColumn::DefaultReleaseDataId => "default_release_data_id",
DraftDataColumn::UserId => "user_id",
@ -218,6 +226,7 @@ impl TableColumn for ReleaseDataColumn {
ReleaseDataColumn::Id => "id",
ReleaseDataColumn::Name => "name",
ReleaseDataColumn::DataType => "data_type",
ReleaseDataColumn::Options => "options",
ReleaseDataColumn::UsedVersionId => "used_version_id",
ReleaseDataColumn::UserId => "user_id",
ReleaseDataColumn::IsPublished => "is_published",

View File

@ -7,6 +7,7 @@ edition = "2021"
prost = "0.13"
async-graphql = { version = "7.0.7", features = ["chrono"] }
sqlx = { workspace = true }
serde = { workspace = true }
[build-dependencies]
prost-build = "0.13"

View File

@ -23,6 +23,11 @@ fn main() {
.out_dir("src/pb")
.type_attribute("common.DataType", "#[derive(sqlx::Type)]")
.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)]")
.compile_protos(
&[

View File

@ -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(
sqlx::Type, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration,

View File

@ -7,6 +7,7 @@ CREATE TABLE
id SERIAL PRIMARY KEY, -- id 自增主键
name VARCHAR(128) NOT NULL, -- 草稿名称
data_type INT NOT NULL, -- 数据类型
options JSONB NULL, -- 数据相关的参数项或配置项
data BYTEA, -- 草稿数据
default_release_data_id INT 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 USING GIN (options);
-- 注释草稿数据表
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.options IS '数据相关的参数项或配置项';
COMMENT ON COLUMN rtss.draft_data.data IS '草稿数据';
COMMENT ON COLUMN rtss.draft_data.user_id IS '创建用户id';
@ -48,6 +54,7 @@ CREATE TABLE
id SERIAL PRIMARY KEY, -- id 自增主键
name VARCHAR(128) NOT NULL UNIQUE, -- 发布数据名称(数据唯一标识)
data_type INT NOT NULL, -- 数据类型
options JSONB NULL, -- 数据相关的参数项或配置项
used_version_id INT NULL, -- 使用的版本数据id
user_id INT NOT NULL, -- 发布/更新用户id
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.options IS '数据相关的参数项或配置项';
COMMENT ON COLUMN rtss.release_data.used_version_id IS '使用的版本数据id';
COMMENT ON COLUMN rtss.release_data.user_id IS '发布/更新用户id';

@ -1 +1 @@
Subproject commit 4e447beffa31c94b30bcee57a7cf229dcf01351f
Subproject commit a1622410919b58683bc0ec059b4f5de575583c13