This commit is contained in:
jeremygan2021
2026-02-12 15:02:53 +08:00
parent b4ac97c3c2
commit 9e81eaaaab
23 changed files with 844 additions and 104 deletions

View File

@@ -1,6 +1,9 @@
from rest_framework import viewsets, status
from rest_framework.decorators import action, api_view
from rest_framework.decorators import action, api_view, parser_classes
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@@ -1309,3 +1312,95 @@ class DistributorViewSet(viewsets.GenericViewSet):
serializer = OrderSerializer(orders, many=True)
return Response(serializer.data)
class WeChatUserViewSet(viewsets.ReadOnlyModelViewSet):
"""
微信用户视图集
"""
queryset = WeChatUser.objects.all()
serializer_class = WeChatUserSerializer
@action(detail=False, methods=['get'])
def stars(self, request):
"""
获取明星技术用户列表
"""
stars = WeChatUser.objects.filter(is_star=True).order_by('-created_at')
serializer = self.get_serializer(stars, many=True)
return Response(serializer.data)
@action(detail=False, methods=['get'], url_path='paid-items')
def paid_items(self, request):
"""
获取当前用户已购买的项目(硬件、课程、服务)
用于论坛发帖时关联
"""
user = get_current_wechat_user(request)
if not user:
return Response({'error': 'Unauthorized'}, status=401)
# 1. 硬件 (ESP32Config)
paid_orders = Order.objects.filter(wechat_user=user, status__in=['paid', 'shipped'])
config_ids = paid_orders.exclude(config__isnull=True).values_list('config_id', flat=True).distinct()
configs = ESP32Config.objects.filter(id__in=config_ids)
# 2. 课程 (VCCourse)
course_ids = paid_orders.exclude(course__isnull=True).values_list('course_id', flat=True).distinct()
courses = VCCourse.objects.filter(id__in=course_ids)
# 3. 服务 (Service)
# 暂时没有强关联 WeChatUser 的 ServiceOrder如果有 phone_number 匹配逻辑可在此添加
# 简单起见,暂不返回服务,或基于 phone_number 匹配
service_orders = ServiceOrder.objects.filter(phone_number=user.phone_number, status='paid')
service_ids = service_orders.values_list('service_id', flat=True).distinct()
services = Service.objects.filter(id__in=service_ids)
return Response({
'configs': ESP32ConfigSerializer(configs, many=True).data,
'courses': VCCourseSerializer(courses, many=True).data,
'services': ServiceSerializer(services, many=True).data
})
@extend_schema(
summary="上传图片",
description="上传图片文件返回图片URL",
request={
'multipart/form-data': {
'type': 'object',
'properties': {
'file': {'type': 'string', 'format': 'binary'}
},
'required': ['file']
}
},
responses={
200: OpenApiExample('成功', value={'url': 'http://.../media/uploads/xxx.jpg'})
}
)
@api_view(['POST'])
@parser_classes([MultiPartParser, FormParser])
def upload_image(request):
file_obj = request.FILES.get('file')
if not file_obj:
return Response({'error': 'No file uploaded'}, status=400)
# 验证文件类型
if not file_obj.content_type.startswith('image/'):
return Response({'error': 'File is not an image'}, status=400)
# 生成唯一文件名
ext = os.path.splitext(file_obj.name)[1]
filename = f"uploads/avatars/{uuid.uuid4()}{ext}"
# 保存文件
path = default_storage.save(filename, ContentFile(file_obj.read()))
# 获取完整URL
# 注意如果使用了云存储url会自动包含域名如果是本地存储可能需要手动拼接
file_url = default_storage.url(path)
# 确保 URL 是完整的 (如果是相对路径,拼接当前 host)
if not file_url.startswith('http'):
file_url = request.build_absolute_uri(file_url)
return Response({'url': file_url})