diff --git a/backend/apps/material/serializers.py b/backend/apps/material/serializers.py index 00538a6..5d67ef0 100644 --- a/backend/apps/material/serializers.py +++ b/backend/apps/material/serializers.py @@ -20,6 +20,10 @@ class MaterialSerializer(serializers.ModelSerializer): """ factory_name = serializers.CharField(source='factory.factory_name', read_only=True) factory_short_name = serializers.CharField(source='factory.short_name', read_only=True) + factory_cooperation_mode = serializers.CharField(source='factory.cooperation_mode', read_only=True, default=None) + factory_cooperation_mode_display = serializers.SerializerMethodField() + factory_province = serializers.CharField(source='factory.province', read_only=True, default=None) + factory_city = serializers.CharField(source='factory.city', read_only=True, default=None) brand = serializers.PrimaryKeyRelatedField( queryset=Brand.objects.all(), allow_null=True, required=False ) @@ -57,10 +61,15 @@ class MaterialSerializer(serializers.ModelSerializer): 'brochure_url', 'quality_level', 'durability_level', 'eco_level', 'carbon_level', 'score_level', 'connection_method', 'construction_method', 'limit_condition', 'factory', 'factory_name', 'factory_short_name', + 'factory_cooperation_mode', 'factory_cooperation_mode_display', + 'factory_province', 'factory_city', 'brand', 'brand_name', 'status', 'created_at', 'updated_at'] read_only_fields = ['id', 'created_at', 'updated_at'] + def get_factory_cooperation_mode_display(self, obj): + return obj.factory.get_cooperation_mode_display() if obj.factory and obj.factory.cooperation_mode else None + def get_brochure_url(self, obj): if obj.brochure: request = self.context.get('request') @@ -85,25 +94,44 @@ class MaterialSerializer(serializers.ModelSerializer): class MaterialListSerializer(serializers.ModelSerializer): """ - 材料列表序列化器(简化版) + 材料列表序列化器(完整字段版,供列表页按需展示列) """ factory_name = serializers.CharField(source='factory.factory_name', read_only=True) factory_short_name = serializers.CharField(source='factory.short_name', read_only=True) + factory_cooperation_mode = serializers.CharField(source='factory.cooperation_mode', read_only=True, default=None) + factory_cooperation_mode_display = serializers.SerializerMethodField() + factory_province = serializers.CharField(source='factory.province', read_only=True, default=None) + factory_city = serializers.CharField(source='factory.city', read_only=True, default=None) brand_name = serializers.CharField(source='brand.name', read_only=True) major_category_display = serializers.CharField(source='get_major_category_display', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) stage_display = serializers.CharField(source='get_stage_display', read_only=True) importance_level_display = serializers.CharField(source='get_importance_level_display', read_only=True) + replace_type_display = serializers.CharField(source='get_replace_type_display', read_only=True) class Meta: model = Material - fields = ['id', 'name', 'major_category', 'major_category_display', + fields = ['id', 'name', 'major_category', 'major_category_display', 'material_category', 'material_subcategory', 'stage', 'stage_display', 'importance_level', 'importance_level_display', 'landing_project', - 'contact_person', 'contact_phone', 'handler', 'remark', 'factory', - 'factory_name', 'factory_short_name', 'brand', 'brand_name', + 'contact_person', 'contact_phone', 'handler', 'remark', + 'spec', 'standard', + 'application_scene', 'application_desc', + 'replace_type', 'replace_type_display', + 'advantage', 'advantage_desc', + 'connection_method', 'construction_method', 'limit_condition', + 'cost_compare', 'cost_desc', 'cases', + 'quality_level', 'durability_level', 'eco_level', + 'carbon_level', 'score_level', + 'factory', 'factory_name', 'factory_short_name', + 'factory_cooperation_mode', 'factory_cooperation_mode_display', + 'factory_province', 'factory_city', + 'brand', 'brand_name', 'status', 'status_display'] + def get_factory_cooperation_mode_display(self, obj): + return obj.factory.get_cooperation_mode_display() if obj.factory and obj.factory.cooperation_mode else None + class MaterialCategorySerializer(serializers.ModelSerializer): """ diff --git a/backend/apps/material/views.py b/backend/apps/material/views.py index 905f94a..9104ef7 100644 --- a/backend/apps/material/views.py +++ b/backend/apps/material/views.py @@ -17,6 +17,7 @@ from rest_framework.parsers import MultiPartParser from .models import Material, MaterialCategory, MaterialSubcategory from .serializers import MaterialSerializer, MaterialListSerializer, MaterialCategorySerializer, MaterialSubcategorySerializer from .importers import import_materials_plan_excel +from apps.factory.models import COOPERATION_MODE_CHOICES def _join_choice_values(values, choices): @@ -149,7 +150,7 @@ class MaterialViewSet(ModelViewSet): """ 根据用户角色过滤材料 """ - queryset = Material.objects.all().order_by('-created_at', '-id') + queryset = Material.objects.select_related('factory', 'brand').order_by('-created_at', '-id') # 普通用户只能看到自己工厂的材料 if self.request.user.role != 'admin': @@ -180,10 +181,10 @@ class MaterialViewSet(ModelViewSet): if major_category: queryset = queryset.filter(major_category=major_category) - # 支持按材料分类过滤 + # 支持按材料分类模糊过滤 material_category = self.request.query_params.get('material_category') if material_category: - queryset = queryset.filter(material_category=material_category) + queryset = queryset.filter(material_category__icontains=material_category) # 支持按材料子类过滤 material_subcategory = self.request.query_params.get('material_subcategory') @@ -200,6 +201,52 @@ class MaterialViewSet(ModelViewSet): if advantage: queryset = queryset.filter(advantage__contains=[advantage]) + # 阶段 + stage = self.request.query_params.get('stage') + if stage: + queryset = queryset.filter(stage=stage) + + # 重要等级 + importance_level = self.request.query_params.get('importance_level') + if importance_level: + queryset = queryset.filter(importance_level=importance_level) + + # 供应商(显式 id 过滤) + factory = self.request.query_params.get('factory') + if factory: + queryset = queryset.filter(factory_id=factory) + + # 合作模式 + cooperation_mode = self.request.query_params.get('factory__cooperation_mode') + if cooperation_mode: + queryset = queryset.filter(factory__cooperation_mode=cooperation_mode) + + # 落地项目(模糊) + landing_project = self.request.query_params.get('landing_project') + if landing_project: + queryset = queryset.filter(landing_project__icontains=landing_project) + + # 成本比较区间 + cost_gte = self.request.query_params.get('cost_compare__gte') + if cost_gte not in (None, ''): + queryset = queryset.filter(cost_compare__gte=cost_gte) + cost_lte = self.request.query_params.get('cost_compare__lte') + if cost_lte not in (None, ''): + queryset = queryset.filter(cost_compare__lte=cost_lte) + + # 综合评分下限 + score_gte = self.request.query_params.get('score_level__gte') + if score_gte not in (None, ''): + queryset = queryset.filter(score_level__gte=score_gte) + + # 对接人 / 经办人 + contact_person = self.request.query_params.get('contact_person') + if contact_person: + queryset = queryset.filter(contact_person__icontains=contact_person) + handler = self.request.query_params.get('handler') + if handler: + queryset = queryset.filter(handler__icontains=handler) + return queryset def get_serializer_class(self): @@ -333,6 +380,7 @@ class MaterialViewSet(ModelViewSet): 'application_scene': Material.APPLICATION_SCENE_CHOICES, 'star_level': Material.STAR_LEVEL_CHOICES, 'status': Material.STATUS_CHOICES, + 'cooperation_mode': COOPERATION_MODE_CHOICES, }) @action(detail=False, methods=['get'], url_path='template')