feat(ai): Day 7 — 会话持久化 Entity + Service

- 新增 3 个 SeaORM Entity: ai_chat_session / ai_chat_message / ai_tool_call_log
- ChatSessionService: create / list / get / close / rename
- ChatMessageService: save_message / list_messages / save_tool_call_log
- 参数封装为 SaveMessageParams / SaveToolCallLogParams 避免 clippy too_many_arguments
- AiState 注册 chat_session + chat_message 服务
- erp-server main.rs 初始化注入
This commit is contained in:
iven
2026-05-19 11:33:37 +08:00
parent b03ea47fed
commit de342f9195
9 changed files with 336 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "ai_chat_messages")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Uuid,
pub tenant_id: Uuid,
pub session_id: Uuid,
pub role: String,
pub content: Option<String>,
pub tool_calls: Option<serde_json::Value>,
pub tool_call_id: Option<String>,
pub token_count: Option<i32>,
pub created_at: DateTimeUtc,
pub updated_at: DateTimeUtc,
pub created_by: Option<Uuid>,
pub updated_by: Option<Uuid>,
pub deleted_at: Option<DateTimeUtc>,
#[sea_orm(default_value = 1)]
pub version_lock: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::ai_chat_session::Entity",
from = "Column::SessionId",
to = "super::ai_chat_session::Column::Id"
)]
Session,
}
impl Related<super::ai_chat_session::Entity> for Entity {
fn to() -> RelationDef {
Relation::Session.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -0,0 +1,37 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "ai_chat_sessions")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Uuid,
pub tenant_id: Uuid,
pub user_id: Uuid,
pub patient_id: Option<Uuid>,
pub title: Option<String>,
#[sea_orm(default_value = "active")]
pub status: String,
pub metadata: Option<serde_json::Value>,
pub created_at: DateTimeUtc,
pub updated_at: DateTimeUtc,
pub created_by: Option<Uuid>,
pub updated_by: Option<Uuid>,
pub deleted_at: Option<DateTimeUtc>,
#[sea_orm(default_value = 1)]
pub version_lock: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::ai_chat_message::Entity")]
Messages,
}
impl Related<super::ai_chat_message::Entity> for Entity {
fn to() -> RelationDef {
Relation::Messages.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -0,0 +1,37 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "ai_tool_call_logs")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: Uuid,
pub tenant_id: Uuid,
pub session_id: Uuid,
pub message_id: Uuid,
pub tool_name: String,
pub parameters: Option<serde_json::Value>,
pub result_summary: Option<String>,
pub execution_ms: Option<i32>,
pub success: bool,
pub created_at: DateTimeUtc,
pub created_by: Option<Uuid>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::ai_chat_session::Entity",
from = "Column::SessionId",
to = "super::ai_chat_session::Column::Id"
)]
Session,
}
impl Related<super::ai_chat_session::Entity> for Entity {
fn to() -> RelationDef {
Relation::Session.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -1,5 +1,7 @@
pub mod ai_analysis;
pub mod ai_analysis_queue;
pub mod ai_chat_message;
pub mod ai_chat_session;
pub mod ai_feature_flags;
pub mod ai_knowledge_guides;
pub mod ai_knowledge_references;
@@ -9,6 +11,7 @@ pub mod ai_risk_threshold;
pub mod ai_suggestion;
pub mod ai_suggestion_feedback;
pub mod ai_tenant_config;
pub mod ai_tool_call_log;
pub mod ai_usage;
pub mod ai_usage_daily;
pub mod copilot_chat_logs;