Files
chunyu_project/user/views/login_record.py
T

138 lines
5.8 KiB
Python

from rest_framework import status
from adrf.views import APIView
from rest_framework.permissions import IsAuthenticated
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from datetime import timedelta
from utils.response_codes import (
ResponseCode,
create_standardized_response,
create_standardized_error_response
)
from ..models import LoginRecord
from ..serializers.user_serializers import LoginRecordSerializer
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from chunyu_project.common_schemas import success_response, error_response, unauthorized_response, not_found_response
@method_decorator(never_cache, name='dispatch')
class LoginRecordListAPIView(APIView):
permission_classes = [IsAuthenticated]
@swagger_auto_schema(
tags=['登录记录'],
operation_summary='获取登录记录列表',
operation_description='获取当前用户的登录记录列表,支持按状态、时间范围筛选和分页',
manual_parameters=[
openapi.Parameter('page', openapi.IN_QUERY, description='页码', type=openapi.TYPE_INTEGER),
openapi.Parameter('page_size', openapi.IN_QUERY, description='每页数量', type=openapi.TYPE_INTEGER),
openapi.Parameter('status', openapi.IN_QUERY, description='登录状态筛选', type=openapi.TYPE_STRING),
openapi.Parameter('time_range', openapi.IN_QUERY, description='时间范围(today/yesterday/7days/30days)', type=openapi.TYPE_STRING),
openapi.Parameter('start_date', openapi.IN_QUERY, description='开始日期(YYYY-MM-DD)', type=openapi.TYPE_STRING),
openapi.Parameter('end_date', openapi.IN_QUERY, description='结束日期(YYYY-MM-DD)', type=openapi.TYPE_STRING),
],
responses={200: success_response, 401: unauthorized_response},
)
async def get(self, request):
user = request.user
page = int(request.query_params.get('page', 1))
page_size = int(request.query_params.get('page_size', 10))
filter_status = request.query_params.get('status', None)
time_range = request.query_params.get('time_range', None)
start_date = request.query_params.get('start_date', None)
end_date = request.query_params.get('end_date', None)
records = LoginRecord.objects.filter(user=user)
if filter_status:
records = records.filter(status=filter_status)
now = timezone.now()
if time_range == 'today':
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
records = records.filter(login_time__gte=today_start)
elif time_range == 'yesterday':
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
yesterday_start = today_start - timedelta(days=1)
records = records.filter(login_time__gte=yesterday_start, login_time__lt=today_start)
elif time_range == '7days':
days_7 = now - timedelta(days=7)
records = records.filter(login_time__gte=days_7)
elif time_range == '30days':
days_30 = now - timedelta(days=30)
records = records.filter(login_time__gte=days_30)
elif start_date and end_date:
records = records.filter(login_time__date__gte=start_date, login_time__date__lte=end_date)
total = await records.acount()
start = (page - 1) * page_size
end = start + page_size
items = [item async for item in records[start:end]]
serializer = LoginRecordSerializer(items, many=True)
return create_standardized_response(
data={
'records': await serializer.adata,
'total': total,
'page': page,
'page_size': page_size,
'total_pages': (total + page_size - 1) // page_size,
},
code=ResponseCode.SUCCESS,
status_code=status.HTTP_200_OK
)
@method_decorator(never_cache, name='dispatch')
class LoginRecordDeleteAPIView(APIView):
permission_classes = [IsAuthenticated]
@swagger_auto_schema(
tags=['登录记录'],
operation_summary='删除登录记录',
operation_description='删除指定的登录记录',
manual_parameters=[
openapi.Parameter('pk', openapi.IN_PATH, description='记录ID', type=openapi.TYPE_INTEGER),
],
responses={200: success_response, 401: unauthorized_response, 404: not_found_response},
)
async def delete(self, request, pk):
user = request.user
try:
record = await LoginRecord.objects.aget(pk=pk, user=user)
await record.adelete()
return create_standardized_response(
code=ResponseCode.SUCCESS,
status_code=status.HTTP_200_OK
)
except LoginRecord.DoesNotExist:
return create_standardized_error_response(
message='记录不存在',
code=ResponseCode.NOT_FOUND,
status_code=status.HTTP_404_NOT_FOUND
)
@method_decorator(never_cache, name='dispatch')
class LoginRecordClearAPIView(APIView):
permission_classes = [IsAuthenticated]
@swagger_auto_schema(
tags=['登录记录'],
operation_summary='清空登录记录',
operation_description='清空当前用户的所有登录记录',
responses={200: success_response, 401: unauthorized_response},
)
async def delete(self, request):
user = request.user
deleted_count, _ = await LoginRecord.objects.filter(user=user).adelete()
return create_standardized_response(
data={'deleted_count': deleted_count},
code=ResponseCode.SUCCESS,
status_code=status.HTTP_200_OK
)