Files
opc-backend/system/views.py
xujl 23855ef0e4 开发了多角色登录与鉴权接口:实现了普通用户、企业和管理员的登录分流,并支持Token验证。
开发了权限控制接口:实现了通过数据库分配菜单权限节点,控制接口访问安全。
开发了实名认证中心:实现了个人身份证信息与企业营业执照的提交与审核接口。
开发了任务与协作大厅核心业务:实现了任务的发布、接单、状态流转以及专家邀约接口。
配置了全局环境变量与数据库引擎:集成了 PostgreSQL 数据库、Redis 缓存与 MinIO 对象存储。
2026-04-28 16:32:02 +08:00

153 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)