Files
hms/crates/erp-ai/src/service/chat_session.rs
iven de342f9195 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 初始化注入
2026-05-19 11:33:37 +08:00

102 lines
3.2 KiB
Rust

use sea_orm::{
ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QueryOrder, Set,
};
use uuid::Uuid;
use crate::entity::ai_chat_session;
pub struct ChatSessionService {
db: DatabaseConnection,
}
impl ChatSessionService {
pub fn new(db: DatabaseConnection) -> Self {
Self { db }
}
pub async fn create(
&self,
tenant_id: Uuid,
user_id: Uuid,
patient_id: Option<Uuid>,
title: Option<String>,
) -> Result<ai_chat_session::Model, sea_orm::DbErr> {
let id = Uuid::now_v7();
let now = chrono::Utc::now();
let model = ai_chat_session::ActiveModel {
id: Set(id),
tenant_id: Set(tenant_id),
user_id: Set(user_id),
patient_id: Set(patient_id),
title: Set(title),
status: Set("active".to_string()),
metadata: Set(None),
created_at: Set(now),
updated_at: Set(now),
created_by: Set(Some(user_id)),
updated_by: Set(Some(user_id)),
deleted_at: Set(None),
version_lock: Set(1),
};
let result = model.insert(&self.db).await?;
Ok(result)
}
pub async fn list(
&self,
tenant_id: Uuid,
user_id: Uuid,
) -> Result<Vec<ai_chat_session::Model>, sea_orm::DbErr> {
ai_chat_session::Entity::find()
.filter(ai_chat_session::Column::TenantId.eq(tenant_id))
.filter(ai_chat_session::Column::UserId.eq(user_id))
.filter(ai_chat_session::Column::DeletedAt.is_null())
.filter(ai_chat_session::Column::Status.ne("closed"))
.order_by_desc(ai_chat_session::Column::UpdatedAt)
.all(&self.db)
.await
}
pub async fn get(
&self,
tenant_id: Uuid,
session_id: Uuid,
) -> Result<Option<ai_chat_session::Model>, sea_orm::DbErr> {
ai_chat_session::Entity::find()
.filter(ai_chat_session::Column::TenantId.eq(tenant_id))
.filter(ai_chat_session::Column::Id.eq(session_id))
.filter(ai_chat_session::Column::DeletedAt.is_null())
.one(&self.db)
.await
}
pub async fn close(&self, tenant_id: Uuid, session_id: Uuid) -> Result<bool, sea_orm::DbErr> {
let session = self.get(tenant_id, session_id).await?;
let Some(session) = session else {
return Ok(false);
};
let mut active: ai_chat_session::ActiveModel = session.into();
active.status = Set("closed".to_string());
active.updated_at = Set(chrono::Utc::now());
active.update(&self.db).await?;
Ok(true)
}
pub async fn rename(
&self,
tenant_id: Uuid,
session_id: Uuid,
new_title: String,
) -> Result<bool, sea_orm::DbErr> {
let session = self.get(tenant_id, session_id).await?;
let Some(session) = session else {
return Ok(false);
};
let mut active: ai_chat_session::ActiveModel = session.into();
active.title = Set(Some(new_title));
active.updated_at = Set(chrono::Utc::now());
active.update(&self.db).await?;
Ok(true)
}
}