From 85ed7a20c1000d161ab826cc166eac452ff8bb5b Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 23 Apr 2026 22:01:59 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A4=A7=E5=B1=8F=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=8C=89=E6=96=B0=E5=93=81=E7=89=8C=E5=AE=9E=E4=BD=93=EF=BC=8C?= =?UTF-8?q?=E6=9D=90=E6=96=99=E7=A7=8D=E7=B1=BB=E7=BB=9F=E8=AE=A1=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E7=BB=86=E5=88=86=E7=A7=8D=E7=B1=BB=E5=B9=B6=E6=8E=92?= =?UTF-8?q?=E9=99=A4=E7=A9=BA=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 材料种类卡片:从 material_subcategory 改为 material_category 去重计数,排除 null/空 - 材料子类分布图:排除 material_subcategory 为空的材料,避免出现 null 类目 - 品牌数卡片:从 Factory.count 改为 Brand.count - 品牌材料分布图:按 material.brand.name 分组,排除无品牌材料;前端字段同步 Co-Authored-By: Claude Opus 4.7 --- backend/apps/statistics/views.py | 41 ++++++++++++++------ frontend/src/views/screen/ScreenOverview.vue | 2 +- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/backend/apps/statistics/views.py b/backend/apps/statistics/views.py index bee28a7..f62fa41 100644 --- a/backend/apps/statistics/views.py +++ b/backend/apps/statistics/views.py @@ -4,6 +4,7 @@ from rest_framework.response import Response from django.db.models import Count from apps.material.models import Material from apps.factory.models import Factory +from apps.brand.models import Brand def _build_brochure_url(request, brochure_field): @@ -27,26 +28,42 @@ def overview_statistics(request): # 材料总数 total_materials = approved_materials.count() - # 材料种类(材料子类数量) - total_material_categories = approved_materials.values('material_subcategory').distinct().count() + # 材料种类(细分种类数量,排除空值) + total_material_categories = ( + approved_materials + .exclude(material_category__isnull=True) + .exclude(material_category='') + .values('material_category') + .distinct() + .count() + ) - # 品牌数(工厂数) - total_brands = Factory.objects.count() + # 品牌数 + total_brands = Brand.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] + # 按材料子类的材料数量分布(排除空值) + material_subcategory_stats = ( + approved_materials + .exclude(material_subcategory__isnull=True) + .exclude(material_subcategory='') + .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') + # 按所属品牌的材料数量分布(排除无品牌的材料) + brand_stats = ( + approved_materials + .exclude(brand__isnull=True) + .values('brand__name') + .annotate(count=Count('id')) + .order_by('-count') + ) # 按省份的工厂数量分布 region_stats = Factory.objects.values('province').annotate( diff --git a/frontend/src/views/screen/ScreenOverview.vue b/frontend/src/views/screen/ScreenOverview.vue index 44742f3..1f51f6b 100644 --- a/frontend/src/views/screen/ScreenOverview.vue +++ b/frontend/src/views/screen/ScreenOverview.vue @@ -113,7 +113,7 @@ const updateCharts = () => { }) const brandData = (stats.value.brand_stats || []).map((item) => ({ - name: item.factory__factory_name, + name: item.brand__name, value: item.count })) charts[2].setOption({