Files

152 lines
5.2 KiB
Python

import json
import logging
from django.db import transaction
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .llm import analyze_requirements
from .models import Requirement, Submission
logger = logging.getLogger(__name__)
def _parse_llm_override(request) -> dict:
raw = request.data.get("llm")
if not raw:
return {}
if isinstance(raw, str):
try:
raw = json.loads(raw)
except json.JSONDecodeError:
return {}
return raw if isinstance(raw, dict) else {}
def _validate_llm_override(override: dict) -> str | None:
if override.get("mode") != "custom":
return None
if not (override.get("base_url") or "").strip() or not (override.get("model") or "").strip():
return "custom 模式必须提供 llm.base_url 和 llm.model"
return None
@api_view(["POST"])
@permission_classes([IsAuthenticated])
@transaction.atomic
def create_requirement(request):
title = (request.data.get("title") or "").strip()
content = (request.data.get("content") or "").strip()
if not title or not content:
return Response({"detail": "title 和 content 不能为空"}, status=status.HTTP_400_BAD_REQUEST)
override = _parse_llm_override(request)
err = _validate_llm_override(override)
if err:
return Response({"detail": err}, status=status.HTTP_400_BAD_REQUEST)
try:
spec = analyze_requirements(content, override)
except Exception:
logger.exception("AI 分析作业要求失败, 使用默认检测计划")
from .llm import _default_spec
spec = _default_spec()
requirement = Requirement.objects.create(
title=title, content=content, spec=spec, llm_config=override,
)
from .serializers import RequirementSerializer
return Response(RequirementSerializer(requirement).data, status=status.HTTP_201_CREATED)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def list_requirements(request):
qs = Requirement.objects.all()
q = request.query_params.get("q")
if q:
qs = qs.filter(title__icontains=q) | qs.filter(content__icontains=q)
from .serializers import RequirementSerializer
page = int(request.query_params.get("page", 1))
size = int(request.query_params.get("size", 20))
items = qs[(page - 1) * size: page * size]
return Response({
"count": qs.count(),
"page": page,
"items": RequirementSerializer(items, many=True).data,
})
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def get_requirement(request, pk):
try:
requirement = Requirement.objects.get(pk=pk)
except Requirement.DoesNotExist:
return Response({"detail": "不存在"}, status=status.HTTP_404_NOT_FOUND)
from .serializers import RequirementSerializer
return Response(RequirementSerializer(requirement).data)
@api_view(["POST"])
@permission_classes([IsAuthenticated])
@transaction.atomic
def create_submission(request, pk):
try:
requirement = Requirement.objects.get(pk=pk)
except Requirement.DoesNotExist:
return Response({"detail": "作业要求不存在"}, status=status.HTTP_404_NOT_FOUND)
name = (request.data.get("name") or "").strip()
file = request.FILES.get("file")
if not file:
return Response({"detail": "缺少上传文件 file"}, status=status.HTTP_400_BAD_REQUEST)
submission = Submission.objects.create(
requirement=requirement,
name=name or file.name,
file=file,
submitted_by=request.user,
)
from .tasks import run_submission
try:
run_submission(submission.id)
except Exception:
logger.exception("检测任务启动失败")
submission.status = "failed"
submission.save(update_fields=["status"])
from .serializers import SubmissionSerializer
return Response(SubmissionSerializer(submission).data, status=status.HTTP_201_CREATED)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def list_submissions(request):
qs = Submission.objects.all()
req_id = request.query_params.get("requirement")
if req_id:
qs = qs.filter(requirement_id=req_id)
from .serializers import SubmissionSerializer
return Response({"items": SubmissionSerializer(qs, many=True).data})
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def get_submission(request, pk):
try:
submission = Submission.objects.get(pk=pk)
except Submission.DoesNotExist:
return Response({"detail": "不存在"}, status=status.HTTP_404_NOT_FOUND)
from .serializers import SubmissionSerializer
return Response(SubmissionSerializer(submission).data)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def get_report(request, pk):
try:
submission = Submission.objects.get(pk=pk)
except Submission.DoesNotExist:
return Response({"detail": "不存在"}, status=status.HTTP_404_NOT_FOUND)
if not submission.report:
return Response({"detail": "报告尚未生成", "status": submission.status},
status=status.HTTP_202_ACCEPTED)
return Response(submission.report)