use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum UserIdType {
OpenId,
UnionId,
UserId,
}
impl UserIdType {
pub fn as_str(&self) -> &'static str {
match self {
UserIdType::OpenId => "open_id",
UserIdType::UnionId => "union_id",
UserIdType::UserId => "user_id",
}
}
}
#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr, PartialEq, Eq)]
#[repr(i32)]
pub enum Language {
ZhCn = 1,
EnUs = 2,
JaJp = 3,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DisplayStatus {
pub allow_highlight: bool,
pub allow_search: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Term {
pub key: String,
pub display_status: DisplayStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct OuterInfo {
pub provider: String,
pub outer_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RelatedUser {
pub id: String,
pub title: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RelatedChat {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RelatedDoc {
pub title: Option<String>,
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RelatedOncall {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RelatedLink {
pub title: Option<String>,
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Abbreviation {
pub id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ClassificationRef {
pub id: String,
pub father_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BaikeImage {
pub token: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RelatedMeta {
pub users: Option<Vec<RelatedUser>>,
pub chats: Option<Vec<RelatedChat>>,
pub docs: Option<Vec<RelatedDoc>>,
pub oncalls: Option<Vec<RelatedOncall>>,
pub links: Option<Vec<RelatedLink>>,
pub abbreviations: Option<Vec<Abbreviation>>,
pub classifications: Option<Vec<ClassificationRef>>,
pub images: Option<Vec<BaikeImage>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct I18nEntryDesc {
pub language: Language,
pub description: Option<String>,
pub rich_text: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Statistics {
pub like_count: i32,
pub dislike_count: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub struct EntityInput {
#[serde(default)]
pub main_keys: Vec<Term>,
#[serde(default)]
pub aliases: Option<Vec<Term>>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub related_meta: Option<RelatedMeta>,
#[serde(default)]
pub outer_info: Option<OuterInfo>,
#[serde(default)]
pub rich_text: Option<String>,
#[serde(default)]
pub i18n_descs: Option<Vec<I18nEntryDesc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub struct DraftEntityInput {
#[serde(default)]
pub id: Option<String>,
#[serde(default)]
pub main_keys: Vec<Term>,
#[serde(default)]
pub aliases: Option<Vec<Term>>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub related_meta: Option<RelatedMeta>,
#[serde(default)]
pub outer_info: Option<OuterInfo>,
#[serde(default)]
pub rich_text: Option<String>,
#[serde(default)]
pub i18n_descs: Option<Vec<I18nEntryDesc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub struct DraftUpdateEntityInput {
#[serde(default)]
pub id: Option<String>,
#[serde(default)]
pub main_keys: Vec<Term>,
#[serde(default)]
pub aliases: Option<Vec<Term>>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub related_meta: Option<RelatedMeta>,
#[serde(default)]
pub rich_text: Option<String>,
#[serde(default)]
pub i18n_descs: Option<Vec<I18nEntryDesc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Entity {
pub id: Option<String>,
pub main_keys: Vec<Term>,
pub aliases: Option<Vec<Term>>,
pub description: Option<String>,
pub creator: Option<String>,
pub create_time: Option<String>,
pub updater: Option<String>,
pub update_time: Option<String>,
pub related_meta: Option<RelatedMeta>,
pub statistics: Option<Statistics>,
pub outer_info: Option<OuterInfo>,
pub rich_text: Option<String>,
pub source: Option<i32>,
pub i18n_descs: Option<Vec<I18nEntryDesc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Draft {
pub draft_id: String,
pub entity: Entity,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct I18nClsName {
pub language: Language,
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Classification {
pub id: String,
pub name: Option<String>,
pub father_id: Option<String>,
pub i18n_names: Option<Vec<I18nClsName>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Repo {
pub id: String,
pub name: String,
}
pub type LingoEntity = Entity;
pub type LingoDraft = Draft;
#[cfg(test)]
mod tests {
use super::*;
fn test_roundtrip<T: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug>(
original: &T,
) {
let json = serde_json::to_string(original).expect("序列化失败");
let deserialized: T = serde_json::from_str(&json).expect("反序列化失败");
assert_eq!(original, &deserialized, "roundtrip 后数据不一致");
}
#[test]
fn test_user_id_type_serialization() {
test_roundtrip(&UserIdType::OpenId);
test_roundtrip(&UserIdType::UnionId);
test_roundtrip(&UserIdType::UserId);
}
#[test]
fn test_language_serialization() {
test_roundtrip(&Language::ZhCn);
test_roundtrip(&Language::EnUs);
test_roundtrip(&Language::JaJp);
}
#[test]
fn test_display_status_serialization() {
let status = DisplayStatus {
allow_highlight: true,
allow_search: false,
};
test_roundtrip(&status);
}
#[test]
fn test_term_serialization() {
let term = Term {
key: "测试词条".to_string(),
display_status: DisplayStatus {
allow_highlight: true,
allow_search: true,
},
};
test_roundtrip(&term);
}
#[test]
fn test_outer_info_serialization() {
let info = OuterInfo {
provider: "provider1".to_string(),
outer_id: "outer123".to_string(),
};
test_roundtrip(&info);
}
#[test]
fn test_related_user_serialization() {
let user = RelatedUser {
id: "user123".to_string(),
title: Some("负责人".to_string()),
};
test_roundtrip(&user);
}
#[test]
fn test_related_chat_serialization() {
let chat = RelatedChat {
id: "chat456".to_string(),
};
test_roundtrip(&chat);
}
#[test]
fn test_related_doc_serialization() {
let doc = RelatedDoc {
title: Some("文档标题".to_string()),
url: Some("https://doc.example.com".to_string()),
};
test_roundtrip(&doc);
}
#[test]
fn test_related_oncall_serialization() {
let oncall = RelatedOncall {
id: "oncall789".to_string(),
};
test_roundtrip(&oncall);
}
#[test]
fn test_related_link_serialization() {
let link = RelatedLink {
title: Some("链接标题".to_string()),
url: Some("https://example.com".to_string()),
};
test_roundtrip(&link);
}
#[test]
fn test_abbreviation_serialization() {
let abbr = Abbreviation {
id: Some("abbr123".to_string()),
};
test_roundtrip(&abbr);
}
#[test]
fn test_classification_ref_serialization() {
let class = ClassificationRef {
id: "class456".to_string(),
father_id: Some("father123".to_string()),
};
test_roundtrip(&class);
}
#[test]
fn test_baike_image_serialization() {
let img = BaikeImage {
token: "img_token_123".to_string(),
};
test_roundtrip(&img);
}
#[test]
fn test_related_meta_serialization() {
let meta = RelatedMeta {
users: Some(vec![RelatedUser {
id: "user1".to_string(),
title: None,
}]),
chats: None,
docs: None,
oncalls: None,
links: None,
abbreviations: None,
classifications: None,
images: None,
};
test_roundtrip(&meta);
}
#[test]
fn test_i18n_entry_desc_serialization() {
let desc = I18nEntryDesc {
language: Language::ZhCn,
description: Some("描述".to_string()),
rich_text: Some("<p>富文本</p>".to_string()),
};
test_roundtrip(&desc);
}
#[test]
fn test_statistics_serialization() {
let stats = Statistics {
like_count: 100,
dislike_count: 5,
};
test_roundtrip(&stats);
}
#[test]
fn test_entity_input_serialization() {
let input = EntityInput {
main_keys: vec![Term {
key: "主词条".to_string(),
display_status: DisplayStatus {
allow_highlight: true,
allow_search: true,
},
}],
aliases: None,
description: Some("词条描述".to_string()),
related_meta: None,
outer_info: None,
rich_text: None,
i18n_descs: None,
};
test_roundtrip(&input);
}
#[test]
fn test_entity_serialization() {
let entity = Entity {
id: Some("entity123".to_string()),
main_keys: vec![Term {
key: "词条名".to_string(),
display_status: DisplayStatus {
allow_highlight: true,
allow_search: true,
},
}],
aliases: None,
description: Some("描述".to_string()),
creator: Some("creator1".to_string()),
create_time: Some("1234567890".to_string()),
updater: None,
update_time: None,
related_meta: None,
statistics: None,
outer_info: None,
rich_text: None,
source: Some(1),
i18n_descs: None,
};
test_roundtrip(&entity);
}
#[test]
fn test_classification_serialization() {
let class = Classification {
id: "class123".to_string(),
name: Some("分类名称".to_string()),
father_id: Some("father123".to_string()),
i18n_names: None,
};
test_roundtrip(&class);
}
#[test]
fn test_repo_serialization() {
let repo = Repo {
id: "repo123".to_string(),
name: "词库名称".to_string(),
};
test_roundtrip(&repo);
}
#[test]
fn test_i18n_cls_name_serialization() {
let name = I18nClsName {
language: Language::EnUs,
name: "English Name".to_string(),
};
test_roundtrip(&name);
}
}