feat:历史记录关于user_id限制

This commit is contained in:
liailing1026
2026-03-09 10:28:07 +08:00
parent 8926480e62
commit 14b79bc282
6 changed files with 69 additions and 19 deletions

View File

@@ -64,11 +64,15 @@ class MultiAgentTaskCRUD:
@staticmethod @staticmethod
def get_recent( def get_recent(
db: Session, limit: int = 20, offset: int = 0 db: Session, limit: int = 20, offset: int = 0, user_id: str = None
) -> List[MultiAgentTask]: ) -> List[MultiAgentTask]:
"""获取最近的任务记录,置顶的排在最前面""" """获取最近的任务记录,置顶的排在最前面"""
query = db.query(MultiAgentTask)
# 按 user_id 过滤
if user_id:
query = query.filter(MultiAgentTask.user_id == user_id)
return ( return (
db.query(MultiAgentTask) query
.order_by(MultiAgentTask.is_pinned.desc(), MultiAgentTask.created_at.desc()) .order_by(MultiAgentTask.is_pinned.desc(), MultiAgentTask.created_at.desc())
.offset(offset) .offset(offset)
.limit(limit) .limit(limit)

View File

@@ -534,8 +534,8 @@ def handle_generate_base_plan_ws(data):
Request_Cache[requestIdentifier] = basePlan_withRenderSpec Request_Cache[requestIdentifier] = basePlan_withRenderSpec
# 保存到数据库 # 保存到数据库
user_id = incoming_data.get("user_id", "default_user") user_id = incoming_data.get("user_id")
task_id = incoming_data.get("task_id") or str(uuid.uuid4()) task_id = incoming_data.get("task_id")
generation_id = str(uuid.uuid4()) generation_id = str(uuid.uuid4())
with get_db_context() as db: with get_db_context() as db:
@@ -1671,9 +1671,21 @@ def handle_get_agents_ws(data):
""" """
WebSocket版本获取智能体配置 WebSocket版本获取智能体配置
从 user_agents 数据库表读取 从 user_agents 数据库表读取
如果没有 user_id会生成新的 user_id 并返回
""" """
request_id = data.get('id') request_id = data.get('id')
user_id = data.get('user_id', 'default_user') # 前端发送的数据在 data 字段中
incoming_data = data.get('data', {})
user_id = incoming_data.get('user_id') if isinstance(incoming_data, dict) else None
# 如果没有 user_id生成新的
new_user_id = None
if not user_id:
new_user_id = str(uuid.uuid4())
user_id = new_user_id
print(f"[get_agents] 新生成 user_id: {new_user_id}")
else:
print(f"[get_agents] 接收到的 user_id: {user_id}")
try: try:
# 从数据库获取用户的智能体配置 # 从数据库获取用户的智能体配置
@@ -1694,14 +1706,20 @@ def handle_get_agents_ws(data):
'apiModel': config.get('apiModel', ''), 'apiModel': config.get('apiModel', ''),
}) })
response_data = {
'code': 200,
'content': 'get agents successfully',
'agents': agents
}
# 如果生成了新的 user_id返回给前端
if new_user_id:
response_data['user_id'] = new_user_id
emit('response', { emit('response', {
'id': request_id, 'id': request_id,
'status': 'success', 'status': 'success',
'data': { 'data': response_data
'code': 200,
'content': 'get agents successfully',
'agents': agents
}
}) })
except Exception as e: except Exception as e:
@@ -1929,14 +1947,18 @@ def handle_get_plans(data):
WebSocket版本获取历史任务列表 WebSocket版本获取历史任务列表
""" """
# socketio 会把数据包装多层: # socketio 会把数据包装多层:
# 前端发送: { id: 'get_plans-xxx', action: 'get_plans', data: { id: 'ws_req_xxx' } } # 前端发送: { id: 'get_plans-xxx', action: 'get_plans', data: { id: 'ws_req_xxx', user_id: 'xxx' } }
# socketio 包装后: data = { id: 'get_plans-xxx', action: 'get_plans', data: {...} } # socketio 包装后: data = { id: 'get_plans-xxx', action: 'get_plans', data: {...} }
request_id = data.get('id') # socketio 包装的 id用于响应匹配 request_id = data.get('id') # socketio 包装的 id用于响应匹配
# 获取 user_id从 data.data 中获取,因为前端发送时会包装)
incoming_data = data.get('data', {})
user_id = incoming_data.get('user_id') if isinstance(incoming_data, dict) else None
try: try:
with get_db_context() as db: with get_db_context() as db:
# 获取最近的任务记录 # 获取最近的任务记录,按 user_id 过滤
tasks = MultiAgentTaskCRUD.get_recent(db, limit=50) tasks = MultiAgentTaskCRUD.get_recent(db, limit=50, user_id=user_id)
# 转换为前端期望的格式 # 转换为前端期望的格式
plans = [] plans = []

View File

@@ -92,7 +92,12 @@ class Api {
setAgents = (data: Pick<Agent, 'Name' | 'Profile' | 'apiUrl' | 'apiKey' | 'apiModel'>[]) => setAgents = (data: Pick<Agent, 'Name' | 'Profile' | 'apiUrl' | 'apiKey' | 'apiModel'>[]) =>
websocket.send('set_agents', data) websocket.send('set_agents', data)
getAgents = (user_id: string = 'default_user') => websocket.send('get_agents', { user_id }) getAgents = (user_id?: string) => {
// 优先使用传入的 user_id其次使用 localStorage 存储的,首次访问时不传
const storedUserId = localStorage.getItem('user_id')
const sendUserId = user_id || storedUserId
return websocket.send('get_agents', sendUserId ? { user_id: sendUserId } : {})
}
generateBasePlan = (data: { generateBasePlan = (data: {
goal: string goal: string
@@ -106,8 +111,9 @@ class Api {
message?: string message?: string
[key: string]: any [key: string]: any
}) => void }) => void
}) => }) => {
websocket.send( const storedUserId = localStorage.getItem('user_id')
return websocket.send(
'generate_base_plan', 'generate_base_plan',
{ {
'General Goal': data.goal, 'General Goal': data.goal,
@@ -115,10 +121,12 @@ class Api {
apiUrl: data.apiUrl, apiUrl: data.apiUrl,
apiKey: data.apiKey, apiKey: data.apiKey,
apiModel: data.apiModel, apiModel: data.apiModel,
...(storedUserId ? { user_id: storedUserId } : {}),
}, },
undefined, undefined,
data.onProgress, data.onProgress,
) )
}
/** /**
* 优化版流式执行计划(支持动态追加步骤) * 优化版流式执行计划(支持动态追加步骤)
@@ -830,10 +838,12 @@ class Api {
throw new Error('WebSocket未连接') throw new Error('WebSocket未连接')
} }
const storedUserId = localStorage.getItem('user_id')
const sendUserId = params.user_id || storedUserId
const rawResponse = await websocket.send('export', { const rawResponse = await websocket.send('export', {
task_id: params.task_id, task_id: params.task_id,
export_type: params.export_type, export_type: params.export_type,
user_id: params.user_id || 'anonymous', ...(sendUserId ? { user_id: sendUserId } : {}),
}) })
const response = this.extractResponse<{ const response = this.extractResponse<{

View File

@@ -15,6 +15,12 @@ const agentsStore = useAgentsStore()
// 如果agentsStore.agents不存在就读取默认配置的json文件 // 如果agentsStore.agents不存在就读取默认配置的json文件
onMounted(async () => { onMounted(async () => {
// 先调用 getAgents检查是否需要生成 user_id
const res = await api.getAgents()
if (res && res.user_id) {
console.log('[AgentRepo] 获取到 user_id:', res.user_id)
}
if (!agentsStore.agents.length) { if (!agentsStore.agents.length) {
const res = await readConfig<Agent[]>('agent.json') const res = await readConfig<Agent[]>('agent.json')
agentsStore.setAgents(res) agentsStore.setAgents(res)

View File

@@ -115,9 +115,10 @@ const historyUpdatedHandler = () => {
const fetchPlans = async () => { const fetchPlans = async () => {
loading.value = true loading.value = true
const reqId = generateRequestId() const reqId = generateRequestId()
const userId = localStorage.getItem('user_id')
try { try {
const result = await websocket.send('get_plans', { id: reqId }) const result = await websocket.send('get_plans', { id: reqId, user_id: userId })
plans.value = (result.data || []) as PlanInfo[] plans.value = (result.data || []) as PlanInfo[]
} catch (error) { } catch (error) {
console.error('获取任务列表失败:', error) console.error('获取任务列表失败:', error)

View File

@@ -105,11 +105,18 @@ class WebSocketClient {
const resolvedGenerationId = generation_id || (data && typeof data === 'object' && !Array.isArray(data) && data.generation_id) const resolvedGenerationId = generation_id || (data && typeof data === 'object' && !Array.isArray(data) && data.generation_id)
const resolvedExecutionId = execution_id || (data && typeof data === 'object' && !Array.isArray(data) && data.execution_id) const resolvedExecutionId = execution_id || (data && typeof data === 'object' && !Array.isArray(data) && data.execution_id)
// user_id 在 data 里面(后端返回格式:{ data: { user_id: 'xxx', ... } }
const resolvedUserId = data && typeof data === 'object' && !Array.isArray(data) && data.user_id
if (resolvedUserId) {
localStorage.setItem('user_id', resolvedUserId)
}
// 直接返回 data保持原始数据结构数组或对象 // 直接返回 data保持原始数据结构数组或对象
handler.resolve({ handler.resolve({
data, data,
generation_id: resolvedGenerationId, generation_id: resolvedGenerationId,
execution_id: resolvedExecutionId execution_id: resolvedExecutionId,
user_id: resolvedUserId
}) })
} else { } else {
handler.reject(new Error(error || 'Unknown error')) handler.reject(new Error(error || 'Unknown error'))