252 lines
6.7 KiB
Python
252 lines
6.7 KiB
Python
from __future__ import annotations
|
||
|
||
from .shared import *
|
||
from .schemas import BlockerResolveRequest, CodeCommentScanRequest, DailyBriefingResponse
|
||
|
||
@router.get("/daily-briefing")
|
||
async def get_daily_briefing(
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
获取个性化每日简报
|
||
|
||
AI 为每个角色生成定制化简报,只包含:
|
||
- 与你相关的任务变更
|
||
- 风险提醒
|
||
- 需要对齐的事项
|
||
- 高影响信号
|
||
- 团队更新
|
||
|
||
彻底过滤无关信息,替代传统日报/周报
|
||
"""
|
||
try:
|
||
service = get_daily_briefing_service(db)
|
||
briefing = await service.generate_personalized_briefing(
|
||
user_id=int(current_user.id),
|
||
tenant_id=tenant_id
|
||
)
|
||
return briefing
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"生成简报失败: {str(e)}"
|
||
)
|
||
|
||
@router.get("/daily-briefing/team/{project_id}")
|
||
async def get_team_briefing(
|
||
project_id: int,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
获取团队简报(给管理者)
|
||
|
||
包含:
|
||
- 整体进度
|
||
- 每个成员的工作量
|
||
- 风险和阻塞
|
||
- 需要决策的事项
|
||
"""
|
||
try:
|
||
service = get_daily_briefing_service(db)
|
||
briefing = await service.generate_team_briefing(
|
||
project_id=project_id,
|
||
tenant_id=tenant_id
|
||
)
|
||
return briefing
|
||
except ValueError as e:
|
||
raise HTTPException(status_code=404, detail=str(e))
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"生成团队简报失败: {str(e)}"
|
||
)
|
||
|
||
@router.post("/analyze-blocker")
|
||
async def analyze_blocker(
|
||
code_context: str,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
分析代码阻塞
|
||
|
||
当开发在代码注释中提到「这个接口达不到效果」时,
|
||
AI 自动触发分析,推荐替代方案或生成代码片段
|
||
"""
|
||
from ..services.llm import LLMService
|
||
|
||
service = get_ai_steward_service(db)
|
||
|
||
prompt = f"""分析以下代码/注释中提到的问题,提供解决方案:
|
||
|
||
代码上下文:
|
||
{code_context}
|
||
|
||
请提供:
|
||
1. 问题分析
|
||
2. 推荐的替代方案
|
||
3. 示例代码(如适用)
|
||
|
||
以 JSON 格式返回。"""
|
||
|
||
try:
|
||
llm = LLMService()
|
||
response = await llm.generate(
|
||
prompt,
|
||
db=db,
|
||
tenant_id=tenant_id,
|
||
)
|
||
|
||
return {
|
||
'analysis': response,
|
||
'suggestions': [],
|
||
'auto_generated': True
|
||
}
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"分析失败: {str(e)}"
|
||
)
|
||
|
||
@router.post("/blockers/scan-comment")
|
||
async def scan_code_comment_for_blockers(
|
||
request: CodeCommentScanRequest,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
扫描代码注释,检测阻塞
|
||
|
||
自动识别阻塞模式:
|
||
- "等待 X 接口完成"
|
||
- "这个 API 达不到效果"
|
||
- "由于 Y 的限制,暂时跳过"
|
||
|
||
如果检测到阻塞,AI 会自动:
|
||
1. 分析严重程度
|
||
2. 生成解决方案建议
|
||
3. 创建追踪任务(如需要)
|
||
"""
|
||
try:
|
||
service = get_blocker_detection_service(db)
|
||
result = await service.scan_code_comment(
|
||
code_content=request.code_content,
|
||
file_path=request.file_path,
|
||
line_number=request.line_number,
|
||
project_id=request.project_id,
|
||
user_id=int(current_user.id),
|
||
tenant_id=tenant_id
|
||
)
|
||
|
||
if result:
|
||
return {
|
||
'status': 'blocker_detected',
|
||
'blocker': result
|
||
}
|
||
|
||
return {
|
||
'status': 'no_blocker',
|
||
'message': '未检测到阻塞'
|
||
}
|
||
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"扫描失败: {str(e)}"
|
||
)
|
||
|
||
@router.post("/blockers/detect-tasks")
|
||
async def detect_task_blockers(
|
||
background_tasks: BackgroundTasks,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
检测所有任务中的阻塞
|
||
|
||
扫描所有超过3天未更新的进行中任务,
|
||
使用 AI 判断是否存在阻塞
|
||
"""
|
||
try:
|
||
service = get_blocker_detection_service(db)
|
||
blockers = await service.detect_task_blockers(tenant_id=tenant_id)
|
||
|
||
return {
|
||
'total_detected': len(blockers),
|
||
'blockers': blockers
|
||
}
|
||
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"检测失败: {str(e)}"
|
||
)
|
||
|
||
@router.get("/blockers/active")
|
||
async def get_active_blockers(
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
获取所有活跃的阻塞
|
||
|
||
返回所有未解决的阻塞,按严重程度排序
|
||
"""
|
||
try:
|
||
service = get_blocker_detection_service(db)
|
||
blockers = await service.get_active_blockers(tenant_id=tenant_id)
|
||
|
||
# 按严重程度排序
|
||
severity_order = {'high': 0, 'medium': 1, 'low': 2}
|
||
blockers.sort(key=lambda b: severity_order.get(b['severity'], 1))
|
||
|
||
return {
|
||
'total': len(blockers),
|
||
'blockers': blockers
|
||
}
|
||
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"获取失败: {str(e)}"
|
||
)
|
||
|
||
@router.post("/blockers/resolve")
|
||
async def resolve_blocker(
|
||
request: BlockerResolveRequest,
|
||
current_user: User = Depends(get_current_user),
|
||
db: AsyncSession = Depends(get_db),
|
||
tenant_id: int = Depends(get_tenant_id)
|
||
):
|
||
"""
|
||
标记阻塞为已解决
|
||
|
||
记录解决方案并关闭阻塞记录
|
||
"""
|
||
try:
|
||
service = get_blocker_detection_service(db)
|
||
result = await service.resolve_blocker(
|
||
blocker_id=request.blocker_id,
|
||
resolution_note=request.resolution_note,
|
||
tenant_id=tenant_id
|
||
)
|
||
|
||
return result
|
||
|
||
except ValueError as e:
|
||
raise HTTPException(status_code=404, detail=str(e))
|
||
except Exception as e:
|
||
raise HTTPException(
|
||
status_code=500,
|
||
detail=f"解决失败: {str(e)}"
|
||
)
|
||
|