This commit is contained in:
2025-10-13 12:27:21 +08:00
parent d3484c57bf
commit bfd79720a9
4 changed files with 80 additions and 52 deletions

View File

@@ -2,11 +2,13 @@ from django.urls import path
from ..views.oj import ( from ..views.oj import (
FlowchartSubmissionAPI, FlowchartSubmissionAPI,
FlowchartSubmissionListAPI, FlowchartSubmissionListAPI,
FlowchartSubmissionRetryAPI FlowchartSubmissionRetryAPI,
FlowchartSubmissionCurrentAPI
) )
urlpatterns = [ urlpatterns = [
path('flowchart/submission', FlowchartSubmissionAPI.as_view()), path('flowchart/submission', FlowchartSubmissionAPI.as_view()),
path('flowchart/submissions', FlowchartSubmissionListAPI.as_view()), path('flowchart/submissions', FlowchartSubmissionListAPI.as_view()),
path('flowchart/submission/retry', FlowchartSubmissionRetryAPI.as_view()), path('flowchart/submission/retry', FlowchartSubmissionRetryAPI.as_view()),
path('flowchart/submission/current', FlowchartSubmissionCurrentAPI.as_view()),
] ]

View File

@@ -4,9 +4,11 @@ from flowchart.models import FlowchartSubmission, FlowchartSubmissionStatus
from flowchart.serializers import ( from flowchart.serializers import (
CreateFlowchartSubmissionSerializer, CreateFlowchartSubmissionSerializer,
FlowchartSubmissionSerializer, FlowchartSubmissionSerializer,
FlowchartSubmissionListSerializer FlowchartSubmissionListSerializer,
) )
from flowchart.tasks import evaluate_flowchart_task from flowchart.tasks import evaluate_flowchart_task
from problem.models import Problem
class FlowchartSubmissionAPI(APIView): class FlowchartSubmissionAPI(APIView):
@login_required @login_required
@@ -15,107 +17,106 @@ class FlowchartSubmissionAPI(APIView):
serializer = CreateFlowchartSubmissionSerializer(data=request.data) serializer = CreateFlowchartSubmissionSerializer(data=request.data)
if not serializer.is_valid(): if not serializer.is_valid():
return self.error(serializer.errors) return self.error(serializer.errors)
data = serializer.validated_data data = serializer.validated_data
# 验证题目存在 # 验证题目存在
try: try:
from problem.models import Problem from problem.models import Problem
problem = Problem.objects.get(_id=data['problem_id'])
problem = Problem.objects.get(id=data["problem_id"])
except Problem.DoesNotExist: except Problem.DoesNotExist:
return self.error("Problem doesn't exist") return self.error("Problem doesn't exist")
# 验证题目是否允许流程图提交 # 验证题目是否允许流程图提交
if not problem.allow_flowchart: if not problem.allow_flowchart:
return self.error("This problem does not allow flowchart submission") return self.error("This problem does not allow flowchart submission")
# 创建提交记录 # 创建提交记录
submission = FlowchartSubmission.objects.create( submission = FlowchartSubmission.objects.create(
user=request.user, user=request.user,
problem=problem, problem=problem,
mermaid_code=data['mermaid_code'], mermaid_code=data["mermaid_code"],
flowchart_data=data.get('flowchart_data', {}) flowchart_data=data.get("flowchart_data", {}),
) )
# 启动AI评分任务 # 启动AI评分任务
evaluate_flowchart_task.send(submission.id) evaluate_flowchart_task.send(submission.id)
return self.success({ return self.success({"submission_id": submission.id, "status": "pending"})
'submission_id': submission.id,
'status': 'pending'
})
@login_required @login_required
def get(self, request): def get(self, request):
"""获取流程图提交详情""" """获取流程图提交详情"""
submission_id = request.GET.get('id') submission_id = request.GET.get("id")
if not submission_id: if not submission_id:
return self.error("submission_id is required") return self.error("submission_id is required")
try: try:
submission = FlowchartSubmission.objects.get(id=submission_id) submission = FlowchartSubmission.objects.get(id=submission_id)
except FlowchartSubmission.DoesNotExist: except FlowchartSubmission.DoesNotExist:
return self.error("Submission doesn't exist") return self.error("Submission doesn't exist")
if not submission.check_user_permission(request.user): if not submission.check_user_permission(request.user):
return self.error("No permission for this submission") return self.error("No permission for this submission")
serializer = FlowchartSubmissionSerializer(submission) serializer = FlowchartSubmissionSerializer(submission)
return self.success(serializer.data) return self.success(serializer.data)
class FlowchartSubmissionListAPI(APIView): class FlowchartSubmissionListAPI(APIView):
@login_required @login_required
def get(self, request): def get(self, request):
"""获取流程图提交列表""" """获取流程图提交列表"""
user_id = request.GET.get('user_id') user_id = request.GET.get("user_id")
problem_id = request.GET.get('problem_id') problem_id = request.GET.get("problem_id")
offset = int(request.GET.get('offset', 0)) offset = int(request.GET.get("offset", 0))
limit = int(request.GET.get('limit', 20)) limit = int(request.GET.get("limit", 20))
queryset = FlowchartSubmission.objects.select_related('user', 'problem') queryset = FlowchartSubmission.objects.select_related("user", "problem")
# 权限过滤 # 权限过滤
if not request.user.is_admin_role(): if not request.user.is_admin_role():
queryset = queryset.filter(user=request.user) queryset = queryset.filter(user=request.user)
# 其他过滤条件 # 其他过滤条件
if user_id: if user_id:
queryset = queryset.filter(user_id=user_id) queryset = queryset.filter(user_id=user_id)
if problem_id: if problem_id:
queryset = queryset.filter(problem_id=problem_id) queryset = queryset.filter(problem_id=problem_id)
total = queryset.count() total = queryset.count()
submissions = queryset[offset:offset + limit] submissions = queryset[offset : offset + limit]
serializer = FlowchartSubmissionListSerializer(submissions, many=True) serializer = FlowchartSubmissionListSerializer(submissions, many=True)
return self.success({ return self.success({"results": serializer.data, "total": total})
'results': serializer.data,
'total': total
})
class FlowchartSubmissionRetryAPI(APIView): class FlowchartSubmissionRetryAPI(APIView):
@login_required @login_required
def post(self, request): def post(self, request):
"""重新触发AI评分""" """重新触发AI评分"""
submission_id = request.data.get('submission_id') submission_id = request.data.get("submission_id")
if not submission_id: if not submission_id:
return self.error("submission_id is required") return self.error("submission_id is required")
try: try:
submission = FlowchartSubmission.objects.get(id=submission_id) submission = FlowchartSubmission.objects.get(id=submission_id)
except FlowchartSubmission.DoesNotExist: except FlowchartSubmission.DoesNotExist:
return self.error("Submission doesn't exist") return self.error("Submission doesn't exist")
# 检查权限 # 检查权限
if not submission.check_user_permission(request.user): if not submission.check_user_permission(request.user):
return self.error("No permission for this submission") return self.error("No permission for this submission")
# 检查是否可以重新评分 # 检查是否可以重新评分
if submission.status not in [FlowchartSubmissionStatus.FAILED, FlowchartSubmissionStatus.COMPLETED]: if submission.status not in [
FlowchartSubmissionStatus.FAILED,
FlowchartSubmissionStatus.COMPLETED,
]:
return self.error("Submission is not in a state that allows retry") return self.error("Submission is not in a state that allows retry")
# 重置状态并重新启动AI评分 # 重置状态并重新启动AI评分
submission.status = FlowchartSubmissionStatus.PENDING submission.status = FlowchartSubmissionStatus.PENDING
submission.ai_score = None submission.ai_score = None
@@ -126,13 +127,37 @@ class FlowchartSubmissionRetryAPI(APIView):
submission.processing_time = None submission.processing_time = None
submission.evaluation_time = None submission.evaluation_time = None
submission.save() submission.save()
# 重新启动AI评分任务 # 重新启动AI评分任务
evaluate_flowchart_task.send(submission.id) evaluate_flowchart_task.send(submission.id)
return self.success({
'submission_id': submission.id,
'status': 'pending',
'message': 'AI evaluation restarted'
})
return self.success(
{
"submission_id": submission.id,
"status": "pending",
"message": "AI evaluation restarted",
}
)
class FlowchartSubmissionCurrentAPI(APIView):
@login_required
def get(self, request):
"""获取当前用户对指定题目的最新流程图提交"""
problem_id = request.GET.get("problem_id")
if not problem_id:
return self.error("problem_id is required")
try:
problem = Problem.objects.get(id=problem_id)
except Problem.DoesNotExist:
return self.error("Problem doesn't exist")
submissions = FlowchartSubmission.objects.filter(
user=request.user, problem=problem
).order_by("-create_time")
count = submissions.count()
if count == 0:
return self.success({"submission": None, "count": 0})
first_submission = submissions[0]
serializer = FlowchartSubmissionSerializer(first_submission)
return self.success({"submission": serializer.data, "count": count})

View File

@@ -185,6 +185,7 @@ class ProblemListSerializer(BaseProblemSerializer):
"tags", "tags",
"contest", "contest",
"rule_type", "rule_type",
"allow_flowchart",
] ]

View File

@@ -89,8 +89,8 @@ def push_flowchart_evaluation_update(submission_id: str, user_id: int, data: dic
logger.warning("Channel layer is not configured, cannot push flowchart evaluation update") logger.warning("Channel layer is not configured, cannot push flowchart evaluation update")
return return
# 构建组名,与 SubmissionConsumer 中的组名一致 # 构建组名,与 FlowchartConsumer 中的组名一致
group_name = f"submission_user_{user_id}" group_name = f"flowchart_user_{user_id}"
try: try:
# 向指定用户组发送消息 # 向指定用户组发送消息
@@ -98,7 +98,7 @@ def push_flowchart_evaluation_update(submission_id: str, user_id: int, data: dic
async_to_sync(channel_layer.group_send)( async_to_sync(channel_layer.group_send)(
group_name, group_name,
{ {
"type": "flowchart_evaluation_update", # 对应 SubmissionConsumer.flowchart_evaluation_update 方法 "type": "flowchart_evaluation_update", # 对应 FlowchartConsumer.flowchart_evaluation_update 方法
"data": data, "data": data,
} }
) )