feat: Add AI report generation with DIFY integration

- Add Users table for display name resolution from AD authentication
- Integrate DIFY AI service for report content generation
- Create docx assembly service with image embedding from MinIO
- Add REST API endpoints for report generation and download
- Add WebSocket notifications for generation progress
- Add frontend UI with progress modal and download functionality
- Add integration tests for report generation flow

Report sections (Traditional Chinese):
- 事件摘要 (Summary)
- 時間軸 (Timeline)
- 參與人員 (Participants)
- 處理過程 (Resolution Process)
- 目前狀態 (Current Status)
- 最終處置結果 (Final Resolution)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-04 18:32:40 +08:00
parent 77091eefb5
commit 3927441103
32 changed files with 4374 additions and 8 deletions

View File

@@ -0,0 +1,53 @@
"""Dependencies for report generation routes
Provides permission checks for report-related operations.
"""
from fastapi import Depends, HTTPException, status
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.modules.auth import get_current_user
from app.modules.chat_room.services.membership_service import membership_service
from app.modules.chat_room.models import IncidentRoom
def require_room_member(room_id: str, db: Session = Depends(get_db), current_user: dict = Depends(get_current_user)):
"""Verify user is a member of the room
Args:
room_id: Room ID to check membership for
db: Database session
current_user: Current authenticated user
Returns:
dict with room_id and user_email
Raises:
HTTPException 404: If room not found
HTTPException 403: If user is not a member
"""
user_email = current_user["username"]
# Check if room exists
room = db.query(IncidentRoom).filter(IncidentRoom.room_id == room_id).first()
if not room:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Room not found"
)
# Check if user is a member (or admin)
is_admin = membership_service.is_system_admin(user_email)
if not is_admin:
role = membership_service.get_user_role_in_room(db, room_id, user_email)
if not role:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="You are not a member of this room"
)
return {
"room_id": room_id,
"user_email": user_email,
"room": room,
}