from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from django.db.models import Count from apps.material.models import Material from apps.factory.models import Factory def _build_brochure_url(request, brochure_field): if brochure_field and request: return request.build_absolute_uri(brochure_field.url) return None @api_view(['GET']) @permission_classes([IsAuthenticated]) def overview_statistics(request): """ 数据总览统计 """ # 只有管理员可访问 if request.user.role != 'admin': return Response({"detail": "无权访问"}, status=403) approved_materials = Material.objects.filter(status='approved') # 材料总数 total_materials = approved_materials.count() # 材料种类(材料子类数量) total_material_categories = approved_materials.values('material_subcategory').distinct().count() # 品牌数(工厂数) total_brands = Factory.objects.count() # 按专业类别的材料数量分布 major_category_stats = approved_materials.values('major_category').annotate( count=Count('id') ).order_by('-count') # 按材料子类的材料数量分布 material_subcategory_stats = approved_materials.values('material_subcategory').annotate( count=Count('id') ).order_by('-count')[:10] # 按所属品牌的材料数量分布 brand_stats = approved_materials.values('factory__factory_name').annotate( count=Count('id') ).order_by('-count') # 按地区的工厂数量分布 region_stats = Factory.objects.values('province', 'city').annotate( count=Count('id') ).order_by('-count') # 应用案例列表 cases_list = [] for item in approved_materials.filter(cases__isnull=False).exclude(cases='')[:10]: cases_list.append({ 'id': item.id, 'name': item.name, 'cases': item.cases, 'factory_name': item.factory.factory_name if item.factory else None, 'brochure_url': _build_brochure_url(request, item.brochure), }) return Response({ 'total_materials': total_materials, 'total_material_categories': total_material_categories, 'total_brands': total_brands, 'major_category_stats': list(major_category_stats), 'material_subcategory_stats': list(material_subcategory_stats), 'brand_stats': list(brand_stats), 'region_stats': list(region_stats), 'cases_list': cases_list, }) @api_view(['GET']) @permission_classes([IsAuthenticated]) def material_statistics(request): """ 材料库统计 """ if request.user.role != 'admin': return Response({"detail": "无权访问"}, status=403) material_subcategory = request.query_params.get('material_subcategory') queryset = Material.objects.filter(status='approved') if material_subcategory: queryset = queryset.filter(material_subcategory=material_subcategory) subcategories = list(Material.objects.filter(status='approved').values_list( 'material_subcategory', flat=True ).distinct()) def _level_counts(qs, field): raw = qs.values(field).annotate(count=Count('id')) mapping = {item[field]: item['count'] for item in raw if item[field] is not None} return [mapping.get(1, 0), mapping.get(2, 0), mapping.get(3, 0)] star_stats = { 'quality_level': _level_counts(queryset, 'quality_level'), 'durability_level': _level_counts(queryset, 'durability_level'), 'eco_level': _level_counts(queryset, 'eco_level'), 'carbon_level': _level_counts(queryset, 'carbon_level'), 'score_level': _level_counts(queryset, 'score_level'), } # 竞争优势与替代材料对比(优势为多选) advantage_replace_counter = {} for material in queryset: advantages = material.advantage or [] for adv in advantages: key = (adv, material.replace_type) advantage_replace_counter[key] = advantage_replace_counter.get(key, 0) + 1 advantage_replace_stats = [ {'advantage': key[0], 'replace_type': key[1], 'count': count} for key, count in advantage_replace_counter.items() ] # 应用场景对比(多选) application_scene_counter = {} for material in queryset: scenes = material.application_scene or [] for scene in scenes: application_scene_counter[scene] = application_scene_counter.get(scene, 0) + 1 application_scene_stats = [ {'application_scene': key, 'count': count} for key, count in application_scene_counter.items() ] # 材料列表 materials_list = [] for item in queryset[:20]: materials_list.append({ 'id': item.id, 'name': item.name, 'material_category': item.material_category, 'material_subcategory': item.material_subcategory, 'factory_name': item.factory.factory_name if item.factory else None, 'brochure_url': _build_brochure_url(request, item.brochure), }) return Response({ 'levels': [1, 2, 3], 'subcategories': subcategories, 'star_stats': star_stats, 'advantage_replace_stats': advantage_replace_stats, 'application_scene_stats': application_scene_stats, 'materials_list': materials_list, 'advantage_choices': Material.ADVANTAGE_CHOICES, 'replace_type_choices': Material.REPLACE_TYPE_CHOICES, 'application_scene_choices': Material.APPLICATION_SCENE_CHOICES, }) @api_view(['GET']) @permission_classes([IsAuthenticated]) def factory_statistics(request): """ 工厂库统计 """ if request.user.role != 'admin': return Response({"detail": "无权访问"}, status=403) region_stats = list(Factory.objects.values('province', 'city').annotate( count=Count('id') ).order_by('-count')) factory_category_stats = [] approved_materials = Material.objects.filter(status='approved') for factory in Factory.objects.all(): material_categories = approved_materials.filter(factory=factory).values( 'material_category' ).annotate( count=Count('id') ) factory_category_stats.append({ 'factory_id': factory.id, 'factory_name': factory.factory_name, 'categories': list(material_categories), 'total_materials': approved_materials.filter(factory=factory).count() }) factories_list = list(Factory.objects.values( 'id', 'factory_name', 'factory_short_name', 'province', 'city', 'website' )) return Response({ 'region_stats': region_stats, 'factory_category_stats': factory_category_stats, 'factories_list': factories_list, })