feat(backend): knowledge iteration + vision + neo4j + response contract source

dependencies.py 拆分为 dependencies/ 包; 新增 vision/ragflow_ingestion/neo4j 客户端与 h5_ai_task; alembic 045 图置信度迁移; 响应契约统一收尾。
This commit is contained in:
Simon
2026-07-09 11:47:16 +08:00
parent f5374fce9b
commit ead5f83bee
39 changed files with 5276 additions and 545 deletions
+12 -6
View File
@@ -144,26 +144,32 @@ async def list_user_role_assignments(
Returns:
List of user role assignments with employee_id, role info, source, etc.
"""
# 使用 LEFT OUTER JOIN:即使 user_roles.role_id 在 roles 表中已不存在
# (例如角色被重建导致 UUID 变化),也保留该条分配记录,避免已分配用户被静默隐藏。
# assigned_at 定义为 NOT NULLnulls_last() 无意义,直接降序即可(SQLite/PG 通用)。
stmt = (
select(UserRole, Role)
.join(Role, UserRole.role_id == Role.id)
.order_by(UserRole.assigned_at.desc().nulls_last())
.outerjoin(Role, UserRole.role_id == Role.id)
.order_by(UserRole.assigned_at.desc())
)
result = await db.execute(stmt)
rows = result.all()
assignments = []
for user_role, role in rows:
# role 可能为 None(孤儿记录),做兜底展示,而不是丢弃该用户
role_name = role.name if role else "unknown"
role_display = (role.display_name or role.name) if role else "未知角色"
assignments.append({
"employee_id": user_role.employee_id,
"role_name": role.name,
"role_display_name": role.display_name or role.name,
"role_name": role_name,
"role_display_name": role_display,
"source": user_role.source or "manual",
"assigned_by": user_role.assigned_by or "",
"assigned_at": user_role.assigned_at.isoformat() if user_role.assigned_at else None,
"expires_at": user_role.expires_at.isoformat() if user_role.expires_at else None,
})
return success_response(data=assignments)