feat: 租户管理体系建设 CRUD + 各业务模块接入 tenant_id
1. 新增 Tenant 模型(tenants 表),支持租户创建、重命名、删除 2. 新增 /api/tenants CRUD 蓝图,default 租户不可删除 3. 数据库初始化时自动创建默认租户记录 4. Dashboard 新增租户管理标签页(创建/编辑/删除租户) 5. 各业务模块写入数据时正确传递 tenant_id: - realtime_chat: create_session 和 _save_conversation 支持 tenant_id - dialogue_manager: _save_conversation 和 create_work_order 支持 tenant_id - conversation_history: save_conversation 支持 tenant_id - workorder_sync: sync_from_feishu 支持 tenant_id - websocket_server: create_session 传递 tenant_id - HTTP chat API: create_session 传递 tenant_id - feishu_sync API: 同步时传递 tenant_id - workorders API: 创建工单时传递 tenant_id 6. 网页对话入口添加租户选择器 7. 知识库搜索按租户隔离(realtime_chat 中 _search_knowledge 传递 tenant_id) 8. 初始化时自动加载租户列表填充选择器
This commit is contained in:
@@ -46,16 +46,19 @@ class ConversationHistoryManager:
|
||||
knowledge_used: Optional[List[int]] = None,
|
||||
ip_address: Optional[str] = None,
|
||||
invocation_method: Optional[str] = None,
|
||||
session_id: Optional[str] = None
|
||||
session_id: Optional[str] = None,
|
||||
tenant_id: Optional[str] = None
|
||||
) -> int:
|
||||
"""保存对话记录到数据库和Redis"""
|
||||
conversation_id = 0
|
||||
|
||||
try:
|
||||
from src.core.models import DEFAULT_TENANT
|
||||
# 保存到数据库
|
||||
with db_manager.get_session() as session:
|
||||
conversation = Conversation(
|
||||
session_id=session_id,
|
||||
tenant_id=tenant_id or DEFAULT_TENANT,
|
||||
work_order_id=work_order_id,
|
||||
user_message=user_message,
|
||||
assistant_response=assistant_response,
|
||||
|
||||
@@ -273,13 +273,16 @@ class DialogueManager:
|
||||
work_order_id: Optional[int],
|
||||
user_message: str,
|
||||
assistant_response: str,
|
||||
knowledge_used: str
|
||||
knowledge_used: str,
|
||||
tenant_id: Optional[str] = None
|
||||
) -> int:
|
||||
"""保存对话记录"""
|
||||
try:
|
||||
from src.core.models import DEFAULT_TENANT
|
||||
with db_manager.get_session() as session:
|
||||
conversation = Conversation(
|
||||
work_order_id=work_order_id,
|
||||
tenant_id=tenant_id or DEFAULT_TENANT,
|
||||
user_message=user_message,
|
||||
assistant_response=assistant_response,
|
||||
knowledge_used=knowledge_used,
|
||||
@@ -310,10 +313,12 @@ class DialogueManager:
|
||||
title: str,
|
||||
description: str,
|
||||
category: str,
|
||||
priority: str = "medium"
|
||||
priority: str = "medium",
|
||||
tenant_id: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""创建工单"""
|
||||
try:
|
||||
from src.core.models import DEFAULT_TENANT
|
||||
with db_manager.get_session() as session:
|
||||
work_order = WorkOrder(
|
||||
order_id=f"WO{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
||||
@@ -322,6 +327,7 @@ class DialogueManager:
|
||||
category=category,
|
||||
priority=priority,
|
||||
status="open",
|
||||
tenant_id=tenant_id or DEFAULT_TENANT,
|
||||
created_at=datetime.now()
|
||||
)
|
||||
session.add(work_order)
|
||||
|
||||
@@ -39,13 +39,14 @@ class RealtimeChatManager:
|
||||
self.active_sessions = {} # 存储活跃的对话会话
|
||||
self.message_history = {} # 存储消息历史
|
||||
|
||||
def create_session(self, user_id: str, work_order_id: Optional[int] = None) -> str:
|
||||
def create_session(self, user_id: str, work_order_id: Optional[int] = None, tenant_id: Optional[str] = None) -> str:
|
||||
"""创建新的对话会话"""
|
||||
session_id = f"session_{user_id}_{int(time.time())}"
|
||||
|
||||
session_data = {
|
||||
"user_id": user_id,
|
||||
"work_order_id": work_order_id,
|
||||
"tenant_id": tenant_id,
|
||||
"created_at": datetime.now(),
|
||||
"last_activity": datetime.now(),
|
||||
"message_count": 0,
|
||||
@@ -57,11 +58,14 @@ class RealtimeChatManager:
|
||||
|
||||
# 持久化会话到数据库
|
||||
try:
|
||||
from src.core.models import DEFAULT_TENANT
|
||||
effective_tenant = tenant_id or DEFAULT_TENANT
|
||||
with db_manager.get_session() as db_session:
|
||||
chat_session = ChatSession(
|
||||
session_id=session_id,
|
||||
user_id=user_id,
|
||||
work_order_id=work_order_id,
|
||||
tenant_id=effective_tenant,
|
||||
status="active",
|
||||
message_count=0,
|
||||
)
|
||||
@@ -96,8 +100,9 @@ class RealtimeChatManager:
|
||||
# 添加到消息历史
|
||||
self.message_history[session_id].append(user_msg)
|
||||
|
||||
# 搜索相关知识
|
||||
knowledge_results = self._search_knowledge(user_message)
|
||||
# 搜索相关知识(按租户隔离)
|
||||
session_tenant = session.get("tenant_id")
|
||||
knowledge_results = self._search_knowledge(user_message, tenant_id=session_tenant)
|
||||
|
||||
# 识别VIN并查询实时数据,注入上下文
|
||||
vin = self._extract_vin(user_message)
|
||||
@@ -180,10 +185,10 @@ class RealtimeChatManager:
|
||||
logger.error(f"处理消息失败: {e}")
|
||||
return {"error": f"处理消息失败: {str(e)}"}
|
||||
|
||||
def _search_knowledge(self, query: str, top_k: int = 3) -> List[Dict[str, Any]]:
|
||||
def _search_knowledge(self, query: str, top_k: int = 3, tenant_id: str = None) -> List[Dict[str, Any]]:
|
||||
"""搜索相关知识"""
|
||||
try:
|
||||
results = self.knowledge_manager.search_knowledge(query, top_k)
|
||||
results = self.knowledge_manager.search_knowledge(query, top_k, tenant_id=tenant_id)
|
||||
return results
|
||||
except Exception as e:
|
||||
logger.error(f"搜索知识库失败: {e}")
|
||||
@@ -474,8 +479,17 @@ class RealtimeChatManager:
|
||||
# 保存知识库使用记录(不再塞 session_marker)
|
||||
knowledge_data = assistant_msg.knowledge_used or []
|
||||
|
||||
# 获取会话的 tenant_id
|
||||
session_tenant = None
|
||||
if session_id in self.active_sessions:
|
||||
session_tenant = self.active_sessions[session_id].get('tenant_id')
|
||||
if not session_tenant:
|
||||
from src.core.models import DEFAULT_TENANT
|
||||
session_tenant = DEFAULT_TENANT
|
||||
|
||||
conversation = Conversation(
|
||||
session_id=session_id,
|
||||
tenant_id=session_tenant,
|
||||
work_order_id=assistant_msg.work_order_id or user_msg.work_order_id,
|
||||
user_message=user_msg.content or "",
|
||||
assistant_response=assistant_msg.content or "",
|
||||
|
||||
Reference in New Issue
Block a user