PMFlow/backend/app/api/endpoints/skill_api/bindings.py

116 lines
3.8 KiB
Python

"""User skill bindings and history endpoints."""
from __future__ import annotations
from typing import List
from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from ....core.database import get_db
from ....dependencies import get_current_user, get_tenant_id
from ....models import User
from ....schemas.skill import (
SkillTaskHistoryItem,
SkillTaskHistoryResponse,
UserSkillBindingBatchUpdate,
UserSkillBindingResponse,
)
from ....services import skill as skill_service
from .shared import ensure_self_or_admin
router = APIRouter()
@router.get("/users/{user_id}/bindings", response_model=List[UserSkillBindingResponse])
async def get_user_skill_bindings(
user_id: int,
tenant_id: int = Depends(get_tenant_id),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
_ = current_user
bindings = await skill_service.get_user_skill_bindings(db, tenant_id, user_id)
return [
UserSkillBindingResponse(
id=str(binding.id),
user_id=str(binding.user_id),
skill_tag_id=str(binding.skill_tag_id),
skill_name=binding.skill_tag.name if binding.skill_tag else "",
proficiency=binding.proficiency or 50,
level=binding.level or binding.proficiency_level or "intermediate",
years_experience=binding.years_experience,
quality_score=getattr(binding, "quality_score", None),
efficiency_score=getattr(binding, "efficiency_score", None),
last_used_at=binding.last_used_at.isoformat() if binding.last_used_at else None,
created_at=binding.created_at.isoformat() if binding.created_at else None,
updated_at=binding.updated_at.isoformat() if binding.updated_at else None,
)
for binding in bindings
]
@router.put("/users/{user_id}/bindings/batch")
async def batch_update_user_skill_bindings(
user_id: int,
body: UserSkillBindingBatchUpdate,
tenant_id: int = Depends(get_tenant_id),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
_ = current_user
bindings = await skill_service.batch_update_user_skill_bindings(
db,
tenant_id,
user_id,
body.bindings,
)
return {"updated_count": len(bindings), "message": "已更新"}
@router.get("/tags/{tag_id}/users")
async def get_skill_tag_users(
tag_id: int,
tenant_id: int = Depends(get_tenant_id),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
_ = current_user
bindings = await skill_service.get_skill_tag_user_bindings(db, tenant_id, tag_id)
return [
{
"user_id": str(binding.user_id),
"user_name": binding.user.name if binding.user else "",
"proficiency": binding.proficiency,
"level": binding.level,
}
for binding in bindings
]
@router.get("/users/{user_id}/tasks", response_model=SkillTaskHistoryResponse)
async def get_user_skill_task_history(
user_id: int,
skill_id: int = Query(..., description="技能标签 ID"),
limit: int = Query(50, ge=1, le=200, description="返回条数上限"),
tenant_id: int = Depends(get_tenant_id),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
ensure_self_or_admin(
current_user=current_user,
target_user_id=user_id,
detail="仅可查询自己的技能历史任务",
)
items = await skill_service.get_user_skill_task_history(
db=db,
tenant_id=tenant_id,
user_id=user_id,
skill_tag_id=skill_id,
limit=limit,
)
return SkillTaskHistoryResponse(
items=[SkillTaskHistoryItem(**item) for item in items],
total=len(items),
)