Files
opc-backend/system/views.py

153 lines
6.2 KiB
Python
Raw Permalink Normal View History

from rest_framework import viewsets, generics, permissions, status
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import Announcement, Notification, SystemConfig, AiModel, ModelToken, Skill
from .serializers import AnnouncementSerializer, NotificationSerializer, SystemConfigSerializer, AiModelSerializer, ModelTokenSerializer, SkillSerializer
class AnnouncementViewSet(viewsets.ModelViewSet):
"""
@author: xujl
Api说明: 系统公告接口视图管理员发布全局或定向通知公告前端获取并展示给对应受众
"""
queryset = Announcement.objects.filter(is_deleted=False)
serializer_class = AnnouncementSerializer
def get_queryset(self):
qs = Announcement.objects.filter(is_deleted=False).order_by('-is_recommended', '-recommend_priority', '-created_at')
audience = self.request.query_params.get('audience')
if audience:
qs = qs.filter(target_audience__in=[audience, 'ALL'])
if self.action == 'list' and not self.request.user.is_staff:
qs = qs.filter(is_published=True)
return qs
def get_permissions(self):
if self.action in ['create', 'update', 'partial_update', 'destroy', 'toggle_recommend']:
return [permissions.IsAdminUser()]
return [permissions.AllowAny()]
@action(detail=True, methods=['post'])
def toggle_recommend(self, request, pk=None):
ann = self.get_object()
ann.is_recommended = request.data.get('is_recommended', not ann.is_recommended)
ann.recommend_priority = request.data.get('recommend_priority', ann.recommend_priority)
ann.save(update_fields=['is_recommended', 'recommend_priority'])
return Response({'is_recommended': ann.is_recommended, 'recommend_priority': ann.recommend_priority})
class NotificationViewSet(viewsets.ModelViewSet):
"""
@author: xujl
Api说明: 站内消息通知接口视图用于系统内部产生的各类站内信状态变更通知的拉取和未读/已读状态更新
"""
serializer_class = NotificationSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Notification.objects.filter(user=self.request.user, is_deleted=False)
@action(detail=True, methods=['post'])
def read(self, request, pk=None):
notification = self.get_object()
notification.is_read = True
notification.save()
return Response({'status': '已标记为已读'})
@action(detail=False, methods=['post'])
def read_all(self, request):
self.get_queryset().update(is_read=True)
return Response({'status': '全部标记为已读'})
class SystemConfigViewSet(viewsets.ModelViewSet):
"""
@author: xujl
Api说明: 系统全局动态配置接口视图用于保存字典数据开关配置等避免硬编码参数
"""
queryset = SystemConfig.objects.all()
serializer_class = SystemConfigSerializer
lookup_field = 'config_key'
def get_permissions(self):
if self.action in ['create', 'update', 'partial_update', 'destroy']:
return [permissions.IsAdminUser()]
return [permissions.AllowAny()]
class AiModelViewSet(viewsets.ModelViewSet):
"""
@author: xujl
Api说明: AI模型配置接口视图统一管理平台对接的各大AI平台如OpenAI文心一言等的模型参数及端点
"""
queryset = AiModel.objects.all()
serializer_class = AiModelSerializer
def get_permissions(self):
if self.action in ['create', 'update', 'partial_update', 'destroy']:
return [permissions.IsAdminUser()]
return [permissions.IsAuthenticatedOrReadOnly()]
def get_queryset(self):
qs = super().get_queryset()
if self.action == 'list' and not self.request.user.is_staff:
return qs.filter(is_active=True)
return qs
class ModelTokenViewSet(viewsets.ModelViewSet):
"""
@author: xujl
Api说明: 大模型Token/密钥接口视图安全管理模型请求时使用的Token或API Key认证信息
"""
serializer_class = ModelTokenSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return ModelToken.objects.filter(user=self.request.user)
def perform_create(self, serializer):
# In a real app, this would call MoRouter or another provider
# For now, we generate a mock token
import uuid
mock_token = f"sk-opc-{uuid.uuid4().hex}"
serializer.save(user=self.request.user, token_value=mock_token)
class SkillViewSet(viewsets.ModelViewSet):
"""
@author: xujl
Api说明: 技能字典/用户标签接口视图用于系统内的技能标签池管理以供任务画像和用户画像进行匹配
"""
"""Admin-managed skill/expertise tags. Read-only for non-admins."""
queryset = Skill.objects.all()
serializer_class = SkillSerializer
def get_permissions(self):
if self.action in ['create', 'update', 'partial_update', 'destroy']:
return [permissions.IsAdminUser()]
return [permissions.AllowAny()]
def get_queryset(self):
qs = super().get_queryset()
if self.action == 'list' and not (self.request.user.is_authenticated and self.request.user.is_staff):
return qs.filter(is_active=True)
return qs
from .minio_utils import minio_client
class FileUploadView(generics.GenericAPIView):
"""
@author: xujl
Api说明: 系统通用文件上传接口对接MinIO或S3等对象存储处理前端传入的文件并返回URL外链
"""
permission_classes = [permissions.AllowAny]
def post(self, request):
file_obj = request.FILES.get('file')
if not file_obj:
return Response({'detail': '没有上传文件'}, status=status.HTTP_400_BAD_REQUEST)
folder = request.data.get('folder', 'general')
try:
file_url = minio_client.upload_file(file_obj, folder=folder)
return Response({'url': file_url}, status=status.HTTP_201_CREATED)
except Exception as e:
return Response({'detail': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)