diff --git a/ai/migrations/0004_add_is_pinned_to_aianalysis.py b/ai/migrations/0004_add_is_pinned_to_aianalysis.py new file mode 100644 index 0000000..d37cdad --- /dev/null +++ b/ai/migrations/0004_add_is_pinned_to_aianalysis.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0.4 on 2026-06-04 14:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ai', '0003_alter_aianalysis_model'), + ] + + operations = [ + migrations.AddField( + model_name='aianalysis', + name='is_pinned', + field=models.BooleanField(default=False), + ), + ] diff --git a/ai/models.py b/ai/models.py index c78802c..12bf55a 100644 --- a/ai/models.py +++ b/ai/models.py @@ -11,6 +11,7 @@ class AIAnalysis(models.Model): system_prompt = models.TextField() user_prompt = models.TextField() analysis = models.TextField() + is_pinned = models.BooleanField(default=False) create_time = models.DateTimeField(auto_now_add=True) class Meta: diff --git a/ai/serializers.py b/ai/serializers.py index d73955f..cc0a918 100644 --- a/ai/serializers.py +++ b/ai/serializers.py @@ -9,7 +9,7 @@ class AIAnalysisListSerializer(serializers.ModelSerializer): class Meta: model = AIAnalysis - fields = ["id", "create_time", "username", "class_name"] + fields = ["id", "create_time", "username", "class_name", "is_pinned"] class AIAnalysisDetailSerializer(serializers.ModelSerializer): diff --git a/ai/urls/oj.py b/ai/urls/oj.py index ee332d1..37c81de 100644 --- a/ai/urls/oj.py +++ b/ai/urls/oj.py @@ -7,6 +7,7 @@ from ..views.oj import ( AIHeatmapDataAPI, AIHintAPI, AILoginSummaryAPI, + AIPinnedReportAPI, ClassPKAnalysisAPI, ) @@ -17,5 +18,6 @@ urlpatterns = [ path("ai/hint", AIHintAPI.as_view()), path("ai/heatmap", AIHeatmapDataAPI.as_view()), path("ai/login_summary", AILoginSummaryAPI.as_view()), + path("ai/pinned", AIPinnedReportAPI.as_view()), path("ai/class_pk", ClassPKAnalysisAPI.as_view()), ] diff --git a/ai/views/admin.py b/ai/views/admin.py index d158d0a..fd42704 100644 --- a/ai/views/admin.py +++ b/ai/views/admin.py @@ -1,5 +1,4 @@ from account.decorators import teacher_admin_required -from account.models import User from utils.api import APIView from ..models import AIAnalysis @@ -21,10 +20,26 @@ class AIAnalysisAdminAPI(APIView): username = request.GET.get("username") if username: - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - return self.error("User not found") - qs = qs.filter(user=user) + qs = qs.filter(user__username__icontains=username) + + if request.GET.get("pinned_only") == "true": + pinned = qs.filter(is_pinned=True) + return self.success(AIAnalysisListSerializer(pinned, many=True).data) return self.success(self.paginate_data(request, qs, AIAnalysisListSerializer)) + + @teacher_admin_required + def post(self, request): + report_id = request.data.get("id") + try: + report = AIAnalysis.objects.select_related("user").get(id=report_id) + except AIAnalysis.DoesNotExist: + return self.error("AIAnalysis not found") + + if report.is_pinned: + report.is_pinned = False + else: + AIAnalysis.objects.filter(user=report.user, is_pinned=True).update(is_pinned=False) + report.is_pinned = True + report.save(update_fields=["is_pinned"]) + return self.success({"is_pinned": report.is_pinned}) diff --git a/ai/views/oj.py b/ai/views/oj.py index 11350b1..a6a52ff 100644 --- a/ai/views/oj.py +++ b/ai/views/oj.py @@ -14,6 +14,7 @@ from django.utils.dateparse import parse_datetime from account.decorators import login_required, teacher_admin_required from account.models import User from ai.models import AIAnalysis +from ai.serializers import AIAnalysisDetailSerializer from flowchart.models import FlowchartSubmission, FlowchartSubmissionStatus from problem.models import Problem from submission.models import JudgeStatus, Submission @@ -800,6 +801,16 @@ class ClassPKAnalysisAPI(APIView): return "\n".join(lines) +class AIPinnedReportAPI(APIView): + @login_required + def get(self, request): + try: + report = AIAnalysis.objects.get(user=request.user, is_pinned=True) + except AIAnalysis.DoesNotExist: + return self.success(None) + return self.success(AIAnalysisDetailSerializer(report).data) + + class AIHintAPI(APIView): @login_required def post(self, request):