wushaodong 1 년 전
부모
커밋
d7d14f612f

+ 61 - 0
apps/base.py

@@ -0,0 +1,61 @@
+#coding=utf-8
+
+class Formater():
+    @staticmethod
+    def formatStr(value):
+        res = u''
+        if value != None:
+            try:
+                res = unicode(value)
+            except:
+                pass
+        return res
+
+    @staticmethod
+    def formatCount(value):
+        return int(round(float(value or 0) * 100,0))
+
+    @staticmethod
+    def formatPrice(value):
+        return int(round(float(value or 0) * 100,0))
+
+    @staticmethod
+    def formatCountShow(value):
+        return '%.2f' % (float(value or 0)/100.0)
+
+    @staticmethod
+    def formatPriceShow(value):
+        return '%.2f' % (float(value or 0)/100.0)
+
+    @staticmethod
+    def formatAmount(value):
+        return int(round(float(value or 0) * 10000,0))
+
+    @staticmethod
+    def formatAmountShow(value):
+        return '%.2f' % (float(value or 0) / 10000.0 + 0.0000001)
+
+class CustomFormaterByUser():
+    @staticmethod
+    def formatEmptyStr(value,user):
+        return Formater.formatEmptyStr(value)
+
+    @staticmethod
+    def formatEmptyFloat(value, user):
+        #return round(value or 0, 2)
+        return Formater.formatEmptyFloat(value)
+
+    @staticmethod
+    def formatTime(value,user):
+        return Formater.formatTime(value)
+
+    @staticmethod
+    def formatDate(value, user):
+        return Formater.formatDate(value)
+
+    @staticmethod
+    def formatCountShow(value,user):
+        return Formater.formatCountShow(value)
+    @staticmethod
+    def formatPartAmountShow(value, user):
+        return Formater.formatAmountShow(value)

+ 0 - 0
apps/vehicle/__init__.py


+ 68 - 0
apps/vehicle/filters.py

@@ -0,0 +1,68 @@
+# coding=utf-8
+
+import django_filters
+
+from django.db.models import Q
+
+from apps.vehicle.models import Brand, Series, Model, VehicleImg, VehicleModelImg
+
+
+class BrandFilter(django_filters.FilterSet):
+    name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
+    enabled = django_filters.CharFilter(field_name='enabled')
+    tenant_id = django_filters.CharFilter(field_name='tenant_id')
+    id = django_filters.CharFilter(field_name='id')
+
+    class Meta:
+        model = Brand
+        fields = '__all__'
+
+
+class SeriesFilter(django_filters.FilterSet):
+    name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
+    brand_name = django_filters.CharFilter(field_name='brand__name', lookup_expr='icontains')
+    brand_id = django_filters.CharFilter(field_name='brand_id')
+
+    class Meta:
+        model = Series
+        fields = '__all__'
+
+
+class ModelFilter(django_filters.FilterSet):
+    series_name = django_filters.CharFilter(field_name='series__name', lookup_expr='icontains')
+    brand_name = django_filters.CharFilter(field_name='series__brand__name', lookup_expr='icontains')
+    series_id = django_filters.CharFilter(method='find_base_series_id')
+    search_param = django_filters.CharFilter(method='find_base_search_param')
+    is_hot = django_filters.CharFilter(field_name='is_hot')
+
+    def find_base_series_id(self, queryset, *args):
+        if args[1] and int(args[1]) > 0:
+            queryset = queryset.filter(series_id=args[1])
+        return queryset
+
+    def find_base_search_param(self, queryset, *args):
+        if args[1]:
+            queryset = queryset.filter(
+                Q(series__brand__name__icontains=args[1]) |
+                Q(series__name__icontains=args[1]) |
+                Q(name__icontains=args[1])
+            )
+        return queryset
+
+    class Meta:
+        model = Model
+        fields = '__all__'
+
+
+class VehicleImgFilter(django_filters.FilterSet):
+
+    class Meta:
+        model = VehicleImg
+        fields = '__all__'
+
+
+class VehicleModelImgFilter(django_filters.FilterSet):
+
+    class Meta:
+        model = VehicleModelImg
+        fields = '__all__'

+ 117 - 0
apps/vehicle/models.py

@@ -0,0 +1,117 @@
+# coding=utf-8
+
+from django.db import models
+
+from utils.exceptions import CustomError
+
+from apps.images.models import Images
+
+class Brand(models.Model):
+    name = models.CharField(max_length=100, verbose_name=u"名称")
+    enabled = models.BooleanField(verbose_name=u"在售", default=True)
+    notes = models.CharField(max_length=500, verbose_name=u"备注", null=True)
+    delete = models.BooleanField(verbose_name=u"删除", default=False, editable=False)
+
+    class Meta:
+        db_table = "vehicle_brand"
+        verbose_name = u"品牌"
+        ordering = [ '-id']
+        index_together = (
+            'name',
+        )
+        default_permissions = ()
+
+
+class Series(models.Model):
+    brand = models.ForeignKey(Brand, verbose_name=u"品牌", on_delete=models.PROTECT)
+    thumbnail = models.ForeignKey(Images, verbose_name=u'缩略图', on_delete=models.PROTECT, null=True)
+    name = models.CharField(max_length=100, verbose_name=u"名称")
+    min_price = models.FloatField(verbose_name=u'最低指导价',default=0)
+    enabled = models.BooleanField(verbose_name=u"在售", default=True)
+    is_hot = models.BooleanField(verbose_name=u"热门", default=False)
+    notes = models.CharField(max_length=500, verbose_name=u"备注", null=True)
+    delete = models.BooleanField(verbose_name=u"删除", default=False, editable=False)
+
+    class Meta:
+        db_table = "vehicle_series"
+        verbose_name = u"车系管理"
+        ordering = ['-id']
+        index_together = (
+            'name',
+        )
+        default_permissions = ()
+        permissions = [
+            ('browse_vehicle_series', u'查看'),
+            ('add_vehicle_series', u'添加'),
+            ('edit_vehicle_series', u'修改'),
+            ('delete_vehicle_series', u'删除'),
+        ]
+
+
+class Model(models.Model):
+    series = models.ForeignKey(Series, related_name='model_ref_series', verbose_name=u"车系", on_delete=models.PROTECT)
+    name = models.CharField(max_length=100, verbose_name=u"名称")
+    price = models.BigIntegerField(verbose_name=u'指导价')
+    sale_price = models.BigIntegerField(verbose_name=u'售价')
+    engine = models.CharField(max_length=50, verbose_name=u'发动机',)
+    car_body = models.CharField(max_length=500, verbose_name=u'车身结构',)
+    transmission = models.CharField(max_length=500, verbose_name=u'变速箱',)
+    notes = models.CharField(max_length=500, verbose_name=u"备注", null=True)
+    enabled = models.BooleanField(verbose_name=u'在用', default=True)
+    delete = models.BooleanField(verbose_name=u"删除", default=False, editable=False)
+
+    class Meta:
+        db_table = "vehicle_model"
+        verbose_name = u"车型管理"
+        ordering = ['-id']
+        index_together = (
+            'name',
+        )
+        default_permissions = ()
+        permissions = [
+            ('browse_vehicle_model', u'查看'),
+            ('add_vehicle_model', u'添加'),
+            ('edit_vehicle_model', u'修改'),
+            ('delete_vehicle_model', u'删除'),
+        ]
+
+    @staticmethod
+    def getById(id):
+        try:
+            id = int(id)
+        except:
+            raise CustomError(u'无效的车型id')
+
+        instance = Model.objects.filter(pk=id).first()
+        if not instance:
+            raise CustomError(u'未找到相应的车型')
+        return instance
+
+    def canSale(self):
+        series = self.series
+        brand = series.brand
+        if self.delete or series.delete or brand.delete:
+            return False
+        if not self.enabled or not series.enabled or not brand.enabled:
+            return False
+        return True
+
+
+class VehicleImg(models.Model):
+    vehicle_model = models.ForeignKey(Model, verbose_name=u'车型', on_delete=models.PROTECT)
+    img = models.ForeignKey(Images, verbose_name=u'图片', on_delete=models.PROTECT)
+
+    class Meta:
+        db_table = 'vehicle_img'
+        verbose_name = u'整车图片'
+        default_permissions = ()
+
+class VehicleModelImg(models.Model):
+    vehicle_model = models.ForeignKey(Model, verbose_name=u'车型', on_delete=models.PROTECT)
+    img = models.ForeignKey(Images, verbose_name=u'图片', on_delete=models.PROTECT)
+
+    class Meta:
+        db_table = 'vehicle_model_img'
+        verbose_name = u'车型图片'
+        default_permissions = ()
+

+ 183 - 0
apps/vehicle/serializers.py

@@ -0,0 +1,183 @@
+# coding=utf-8
+
+import json
+from django.conf import settings
+from rest_framework import serializers
+from apps.vehicle.models import Brand, Series, Model, VehicleImg, VehicleModelImg
+from apps.images.models import Images
+
+from utils.exceptions import CustomError
+from apps.base import Formater
+
+
+class BrandSerializer(serializers.ModelSerializer):
+    enabled_text = serializers.SerializerMethodField()
+
+    def get_enabled_text(self, obj):
+        if obj.enabled:
+            return u'是'
+        return u'否'
+
+    class Meta:
+        model = Brand
+        fields = '__all__'
+
+    def create(self, validated_data):
+        instance = super(BrandSerializer, self).create(validated_data)
+        return instance
+
+    def update(self, instance, validated_data):
+        instance = super(BrandSerializer, self).update(instance, validated_data)
+        return instance
+
+
+class SeriesSerializer(serializers.ModelSerializer):
+    brand_name = serializers.CharField(source='brand.name', read_only=True)
+    enabled_text = serializers.SerializerMethodField()
+    img_url = serializers.SerializerMethodField()
+    is_hot_text = serializers.SerializerMethodField()
+
+    def get_is_hot_text(self, obj):
+        if obj.is_hot:
+            return u'是'
+        return u'否'
+
+    def get_enabled_text(self, obj):
+        if obj.enabled:
+            return u'是'
+        return u'否'
+
+    def get_img_url(self, obj):
+        if obj.thumbnail:
+            return '%s%s' % (settings.MEDIA_URL, obj.thumbnail.picture)
+        return ''
+
+    class Meta:
+        model = Series
+        fields = '__all__'
+
+    def create(self, validated_data):
+        user = self.context['request'].user
+        file = self.context['request'].FILES.get('image', None)
+
+        if file:
+            validated_data['thumbnail'] = Images.objects.employee_addnew(user, Images.VEHICLE_SERIES_THUMBNAIL,
+                                                                         file)
+        instance = super(SeriesSerializer, self).create(validated_data)
+        return instance
+
+
+class ModelSerializer(serializers.ModelSerializer):
+    series_name = serializers.CharField(source='series.name', read_only=True)
+    brand_name = serializers.CharField(source='series.brand.name', read_only=True)
+    enabled_text = serializers.SerializerMethodField()
+    hot_text = serializers.SerializerMethodField()
+    thumbnail_url = serializers.SerializerMethodField()
+    price_show = serializers.SerializerMethodField()
+    shop_price_show = serializers.SerializerMethodField()
+    advance_pay_show = serializers.SerializerMethodField()
+    equal_pay_show = serializers.SerializerMethodField()
+    price = serializers.CharField()
+    advance_pay = serializers.CharField()
+    equal_pay = serializers.CharField()
+    commission_ratio = serializers.CharField(required=False)
+    playbill_url = serializers.SerializerMethodField()
+    full_name = serializers.SerializerMethodField()
+    commission_amount = serializers.SerializerMethodField()
+
+    def get_commission_amount(self, obj):
+        if obj.commission_ratio != None:
+            return Formater.formatAmountShow(obj.commission_ratio)
+        return ''
+
+    def get_shop_price_show(self, obj):
+        return Formater.formatAmountShow(obj.shop_price)
+
+    def get_price_show(self, obj):
+        return Formater.formatAmountShow(obj.price)
+
+    def get_advance_pay_show(self, obj):
+        return Formater.formatAmountShow(obj.advance_pay)
+
+    def get_equal_pay_show(self, obj):
+        return Formater.formatAmountShow(obj.equal_pay)
+
+    def get_enabled_text(self, obj):
+        if obj.enabled:
+            return u'是'
+        return u'否'
+
+    def get_hot_text(self, obj):
+        if obj.is_hot:
+            return u'是'
+        return u'否'
+
+    def get_full_name(self, obj):
+        return obj.series.brand.name + '-' + obj.series.name + '-' + obj.name
+
+    def get_thumbnail_url(self, obj):
+        if obj.thumbnail:
+            return '%s%s' % (settings.MEDIA_URL, obj.thumbnail.picture)
+        return ''
+
+    def get_playbill_url(self, obj):
+        if obj.playbill:
+            return '%s%s' % (settings.MEDIA_URL, obj.playbill.picture)
+        return ''
+
+    class Meta:
+        model = Model
+        fields = '__all__'
+
+    def create(self, validated_data):
+        user = self.context['request'].user
+        thumbnail = self.context['request'].FILES.get('image', None)
+        tags = self.context['request'].data.get('tags')
+
+        if thumbnail:
+            validated_data['thumbnail'] = Images.objects.employee_addnew(user.employee, Images.VEHICLE_MODEL_THUMBNAIL,
+                                                                         thumbnail)
+        instance = super(ModelSerializer, self).create(validated_data)
+
+        return instance
+
+    def validate(self, attrs):
+        if 'price' in attrs:
+            attrs['price'] = Formater.formatAmount(attrs['price'])
+        if 'equal_pay' in attrs:
+            attrs['equal_pay'] = Formater.formatAmount(attrs['equal_pay'])
+        if 'advance_pay' in attrs:
+            attrs['advance_pay'] = Formater.formatAmount(attrs['advance_pay'])
+        if 'shop_price' in attrs:
+            attrs['shop_price'] = Formater.formatAmount(attrs['shop_price'])
+        if 'commission_ratio' in attrs and attrs['commission_ratio']:
+            attrs['commission_ratio'] = Formater.formatAmount(attrs['commission_ratio'])
+        else:
+            attrs['commission_ratio'] = None
+        return attrs
+
+
+class VehicleImgSerializer(serializers.ModelSerializer):
+    img_url = serializers.SerializerMethodField()
+
+    def get_img_url(self, obj):
+        if obj.img:
+            return '%s%s' % (settings.MEDIA_URL, obj.img.picture)
+        return ''
+
+    class Meta:
+        model = VehicleImg
+        fields = '__all__'
+
+
+class VehicleModelImgSerializer(serializers.ModelSerializer):
+    img_url = serializers.SerializerMethodField()
+
+    def get_img_url(self, obj):
+        if obj.img:
+            return '%s%s' % (settings.MEDIA_URL, obj.img.picture)
+        return ''
+
+    class Meta:
+        model = VehicleModelImg
+        fields = '__all__'

+ 20 - 0
apps/vehicle/urls.py

@@ -0,0 +1,20 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'dict/$', DictView.as_view()),
+    url(r'series/search/$', VehicleSeriesSearch.as_view()),
+    url(r'model/search/$', VehicleModelSearch.as_view()),
+]
+
+router = SimpleRouter()
+router.register(r'brand', VehicleBrandViewSet)
+router.register(r'series', VehicleSeriesViewSet)
+router.register(r'model', VehicleModelViewSet)
+router.register(r'images', VehicleImageViewSet)
+router.register(r'model_images', VehicleModelImageViewSet)
+urlpatterns += router.urls

+ 309 - 0
apps/vehicle/views.py

@@ -0,0 +1,309 @@
+# coding=utf-8
+
+import json
+import ast
+from django.db import transaction
+from rest_framework.decorators import action
+from rest_framework.views import APIView
+from django.db.models import Q
+from utils import response_ok
+from utils.permission import permission_required, isLogin
+from utils.custom_modelviewset import CustomModelViewSet
+from utils.exceptions import CustomError
+from apps.images.models import Images
+from apps.vehicle.models import Brand, Series, Model, VehicleModelImg, VehicleImg
+from apps.vehicle.filters import BrandFilter, SeriesFilter, ModelFilter, VehicleImgFilter, VehicleModelImgFilter
+from .serializers import BrandSerializer, SeriesSerializer, ModelSerializer, VehicleImgSerializer, VehicleModelImgSerializer
+from apps.account import tenant_log
+from apps.foundation.models import BizLog
+
+class DictView(APIView):
+    permission_classes = [isLogin, ]
+
+    def get(self, request):
+        ret = {
+            'brand': BrandSerializer(Brand.objects.filter(delete=False, enabled=True, ), many=True).data,
+            'series': SeriesSerializer(Series.objects.filter(delete=False, enabled=True, ), many=True).data
+        }
+        return response_ok(ret)
+
+class VehicleBrandViewSet(CustomModelViewSet):
+    permission_classes = [isLogin, ]
+    queryset = Brand.objects.filter(delete=False)
+    serializer_class = BrandSerializer
+
+    def filter_queryset(self, queryset):
+        # queryset = queryset.filter(tenant=self.request.user.employee.tenant)
+        f = BrandFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def perform_create(self, serializer):
+        super(VehicleBrandViewSet, self).perform_create(serializer)
+        instance = serializer.instance
+        validated_data = serializer.validated_data
+        tenant_log(self.request.user, BizLog.INSERT, u'添加整车品牌[%s],id=%d' % (instance.name, instance.id),validated_data)
+
+    def perform_update(self, serializer):
+        super(VehicleBrandViewSet, self).perform_update(serializer)
+        instance = serializer.instance
+        validated_data = serializer.validated_data
+        tenant_log(self.request.user, BizLog.UPDATE, u'修改整车品牌[%s],id=%d' % (instance.name, instance.id), validated_data)
+
+    def destroy(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            instance.delete = True
+            instance.save()
+            tenant_log(self.request.user, BizLog.DELETE, u'删除整车品牌[%s],id=%d' % (instance.name, instance.id))
+        return response_ok()
+
+
+class VehicleSeriesViewSet(CustomModelViewSet):
+    permission_classes = [isLogin, ]
+    queryset = Series.objects.filter(delete=False, brand__delete=False)
+    serializer_class = SeriesSerializer
+
+    def filter_queryset(self, queryset):
+        # queryset = queryset.filter(tenant=self.request.user.employee.tenant)
+        f = SeriesFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def perform_create(self, serializer):
+        super(VehicleSeriesViewSet, self).perform_create(serializer)
+        instance = serializer.instance
+        validated_data = serializer.validated_data
+        tenant_log(self.request.user, BizLog.INSERT, u'添加整车车系[%s],id=%d' % (instance.name, instance.id),validated_data)
+
+    def destroy(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            instance.delete = True
+            instance.save()
+            tenant_log(self.request.user, BizLog.DELETE, u'删除整车车系[%s],id=%d' % (instance.name, instance.id))
+        return response_ok()
+
+    @action(methods=['post'], detail=True)
+    def update_series(self, request, pk):
+        file = request.FILES.get('image', None)
+        user = request.user
+        instance = self.get_object()
+        if instance.delete:
+            raise CustomError(u'该车系已删除,禁止操作!')
+
+        with transaction.atomic():
+            serializer = self.get_serializer(instance, data=request.data)
+            serializer.is_valid(raise_exception=True)
+            self.perform_update(serializer)
+
+            tenant_log(user, BizLog.UPDATE, u'修改车系[%s], id=%d' % (instance.name, instance.id), request.data)
+
+            if file:
+                old_thumbnail = instance.thumbnail
+                thumbnail = Images.objects.employee_addnew(user, Images.VEHICLE_SERIES_THUMBNAIL, file)
+                instance.thumbnail = thumbnail
+                instance.save()
+                if old_thumbnail:
+                    old_thumbnail.del_images()
+        return response_ok()
+
+
+class VehicleModelViewSet(CustomModelViewSet):
+    permission_classes = [isLogin, ]
+    queryset = Model.objects.filter(delete=False, series__delete=False, series__brand__delete=False)
+    serializer_class = ModelSerializer
+
+    def filter_queryset(self, queryset):
+        # queryset = queryset.filter(tenant=self.request.user.employee.tenant)
+        f = ModelFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def perform_create(self, serializer):
+        super(VehicleModelViewSet, self).perform_create(serializer)
+        instance = serializer.instance
+        validated_data = serializer.validated_data
+        tenant_log(self.request.user, BizLog.INSERT, u'添加整车型号[%s],id=%d' % (instance.name, instance.id),validated_data)
+
+    def destroy(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            instance.delete = True
+            instance.save()
+            tenant_log(self.request.user, BizLog.DELETE, u'删除整车型号[%s],id=%d' % (instance.name, instance.id))
+        return response_ok()
+
+    @action(methods=['post'], detail=True)
+    def update_model(self, request, pk):
+        if not self.request.user.has_perm('vehicle_model.edit_vehicle_model'):
+            raise CustomError(u"您没有[车型管理-修改]权限,无法执行该操作,请联系管理员分配权限!")
+        instance = self.get_object()
+        user = request.user
+        thumbnail = request.FILES.get('image', None)
+        tags = request.POST.get('tags')
+
+        if instance.delete:
+            raise CustomError(u'该车型已被删除,禁止操作!')
+
+        with transaction.atomic():
+            serializer = self.get_serializer(instance, data=request.data)
+            serializer.is_valid(raise_exception=True)
+            self.perform_update(serializer)
+
+            tenant_log(self.request.user, BizLog.UPDATE, u'修改整车型号[%s],id=%d' % (instance.name, instance.id), request.data)
+
+            if thumbnail:
+                old_thumbnail = instance.thumbnail
+                thumbnail = Images.objects.employee_addnew(user, Images.VEHICLE_MODEL_THUMBNAIL, thumbnail)
+                instance.thumbnail = thumbnail
+                instance.save()
+                if old_thumbnail:
+                    old_thumbnail.del_images()
+
+        return response_ok()
+
+    @action(methods=['post'], detail=True)
+    def upload_playbill(self, request, pk):
+        # 整车上传海报
+        if not self.request.user.has_perm('vehicle_model.edit_vehicle_model'):
+            raise CustomError(u"您没有[车型管理-修改]权限,无法执行该操作,请联系管理员分配权限!")
+        playbill = request.FILES.get('image', None)
+        user = request.user
+        vehicle_model = self.get_object()
+
+        if vehicle_model.delete:
+            raise CustomError(u'该整车型号已删除,禁止操作!')
+        if not playbill:
+            raise CustomError(u'未找到上传文件!')
+
+        with transaction.atomic():
+            tenant_log(user, BizLog.UPDATE, u'车型[%s]上传海报, id=%d' % (vehicle_model.name, vehicle_model.id))
+            old_playbill = vehicle_model.playbill
+            playbill = Images.objects.employee_addnew(user, Images.VEHICLE_MODEL_PLAYBILL, playbill)
+            vehicle_model.playbill = playbill
+            vehicle_model.save()
+            if old_playbill:
+                old_playbill.del_images()
+
+        return response_ok()
+
+    @action(methods=['post'], detail=True)
+    def set_vehicle_img(self, request, pk):
+        # 设置整车图片
+        if not self.request.user.has_perm('vehicle_model.edit_vehicle_model'):
+            raise CustomError(u"您没有[车型管理-修改]权限,无法执行该操作,请联系管理员分配权限!")
+        image = request.FILES.get('images', None)
+        vehicle_model = self.get_object()
+
+        if vehicle_model.delete:
+            raise CustomError(u'该整车型号已删除,禁止操作!')
+        if not image:
+            raise CustomError(u'未找到上传文件!')
+
+        with transaction.atomic():
+            image = Images.objects.employee_addnew(request.user, Images.VEHICLE_IMAGES, image)
+            VehicleImg.objects.create(vehicle_model=vehicle_model, img=image)
+            tenant_log(request.user, BizLog.DELETE, u'车型[%s]上传整车图片儿,id=%d' % (vehicle_model.name, vehicle_model.id))
+
+        return response_ok()
+
+    @action(methods=['post'], detail=True)
+    def set_model_img(self, request, pk):
+        if not self.request.user.has_perm('vehicle_model.edit_vehicle_model'):
+            raise CustomError(u"您没有[车型管理-修改]权限,无法执行该操作,请联系管理员分配权限!")
+        image = request.FILES.get('images', None)
+        type_id = request.POST.get('type')
+        user = request.user
+        vehicle_model = self.get_object()
+
+        if vehicle_model.delete:
+            raise CustomError(u'该整车型号已删除,禁止操作!')
+        if not image:
+            raise CustomError(u'未找到上传文件!')
+
+        with transaction.atomic():
+            img = Images.objects.employee_addnew(user, Images.VEHICLE_MODEL_IMAGES, image)
+            VehicleModelImg.objects.create(vehicle_model=vehicle_model, img=img)
+            tenant_log(request.user, BizLog.INSERT, u'车型[%s]上传车型分类图片儿,id=%d' % (vehicle_model.name, vehicle_model.id))
+        return response_ok()
+
+
+class VehicleImageViewSet(CustomModelViewSet):
+    permission_classes = [isLogin, ]
+    queryset = VehicleImg.objects.filter()
+    serializer_class = VehicleImgSerializer
+
+    def filter_queryset(self, queryset):
+        f = VehicleImgFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)
+
+    def destroy(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            tenant_log(self.request.user, BizLog.DELETE, u'删除车型[%s]整车图片,id=%d' % (instance.vehicle_model.name, instance.vehicle_model.id))
+            img = instance.img
+            instance.delete()
+            img.del_images()
+        return response_ok()
+
+
+class VehicleModelImageViewSet(CustomModelViewSet):
+    permission_classes = [isLogin, ]
+    queryset = VehicleModelImg.objects.filter()
+    serializer_class = VehicleModelImgSerializer
+
+    def filter_queryset(self, queryset):
+        f = VehicleModelImgFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)
+
+    def destroy(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+
+            tenant_log(self.request.user, BizLog.DELETE, u'删除车型[%s]车型图片,id=%d' % (instance.vehicle_model.name, instance.vehicle_model.id))
+            img = instance.img
+            instance.delete()
+            img.del_images()
+        return response_ok()
+
+class VehicleSeriesSearch(APIView):
+    permission_classes = [isLogin, ]
+
+    def get(self, request):
+        keyword = request.GET.get('keywords')
+        rows = Series.objects.filter(delete=False, enabled=True, brand__delete=False, brand__enabled=True)
+        if keyword:
+            rows = rows.filter(
+                Q(name__icontains=keyword) |
+                Q(brand__name__icontains=keyword)
+            )
+        serializer = SeriesSerializer(rows, many=True)
+        return response_ok(serializer.data)
+
+
+class VehicleModelSearch(APIView):
+    permission_classes = [isLogin, ]
+
+    def get(self, request):
+        keyword = request.GET.get('keyword')
+        rows = Model.objects.filter(
+            delete=False, enabled=True, series__delete=False, series__enabled=True, series__brand__delete=False,
+            series__brand__enabled=True,
+        )
+        if keyword:
+            rows = rows.filter(
+                Q(name__icontains=keyword) |
+                Q(series__brand__name__icontains=keyword)|
+                Q(series__name__icontains=keyword)
+            )
+        serializer = ModelSerializer(rows, many=True)
+        return response_ok(serializer.data)
+

+ 1 - 1
manage.py

@@ -5,7 +5,7 @@ import sys
 
 
 def main():
-    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'markwin.settings')
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'shop.settings')
     try:
         from django.core.management import execute_from_command_line
     except ImportError as exc:

+ 1 - 0
requirements

@@ -4,6 +4,7 @@ djangorestframework
 djangorestframework-jwt
 django-cors-headers
 mysqlclient
+aliyun-python-sdk-core
 Pillow
 pycryptodome
 requests

+ 4 - 4
shop/settings.py

@@ -47,7 +47,7 @@ INSTALLED_APPS = [
     'apps.foundation',
     'apps.usedvehicle',
     'apps.images',
-    # 'apps.shop',
+    'apps.vehicle',
     # 'apps.employee',
     # 'apps.option',
     # 'apps.package',
@@ -145,9 +145,9 @@ DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.mysql',
         'NAME': 'lhyt_shop',
-        'USER': 'root',
-        'PASSWORD': 'lyh123',
-        'HOST': '127.0.0.1',
+        'USER': 'carwin',
+        'PASSWORD': 'carwin!@#',
+        'HOST': '192.168.2.55',
         'PORT': 3306,
     }
 }

+ 1 - 1
shop/urls.py

@@ -26,7 +26,7 @@ urlpatterns = [
     url(r'^account/', include('apps.account.urls')),
     url(r'^foundation/', include('apps.foundation.urls')),
     url(r'^usedvehicle/', include('apps.usedvehicle.urls')),
-    # url(r'^tenant/', include('apps.tenant.urls')),
+    url(r'^vehicle/', include('apps.vehicle.urls')),
     # url(r'^customer/', include('apps.customer.urls')),
     # url(r'^api/', include('apps.api.urls')),
 ]

+ 198 - 189
uis/views/index.html

@@ -1,207 +1,216 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <meta charset="utf-8">
-  <title>小程序商城系统</title>
-  <meta name="renderer" content="webkit">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
-  <link rel="stylesheet" href="../layuiadmin/layui/css/layui.css" media="all">
-  <link rel="stylesheet" href="../layuiadmin/style/admin.css" media="all">
+    <meta charset="utf-8">
+    <title>小程序商城系统</title>
+    <meta name="renderer" content="webkit">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport"
+          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+    <link rel="stylesheet" href="../layuiadmin/layui/css/layui.css" media="all">
+    <link rel="stylesheet" href="../layuiadmin/style/admin.css" media="all">
 </head>
 <body class="layui-layout-body">
-  
-  <div id="LAY_app">
-    <div class="layui-layout layui-layout-admin">
-      <div class="layui-header">
-        <!-- 头部区域 -->
-        <ul class="layui-nav layui-layout-left">
-          <li class="layui-nav-item layadmin-flexible" lay-unselect>
-            <a href="javascript:;" layadmin-event="flexible" title="侧边伸缩">
-              <i class="layui-icon layui-icon-shrink-right" id="LAY_app_flexible"></i>
-            </a>
-          </li>
-          <li class="layui-nav-item" lay-unselect>
-            <a href="javascript:;" layadmin-event="refresh" title="刷新">
-              <i class="layui-icon layui-icon-refresh-3"></i>
-            </a>
-          </li>
-        </ul>
-        <ul class="layui-nav layui-layout-right" lay-filter="layadmin-layout-right">
-          <li class="layui-nav-item layui-hide-xs" lay-unselect>
-            <a href="javascript:;" layadmin-event="theme">
-              <i class="layui-icon layui-icon-theme"></i>
-            </a>
-          </li>
-          <li class="layui-nav-item" lay-unselect>
-            <a href="javascript:;">
-              <cite id="id_username"></cite>
-            </a>
-            <dl class="layui-nav-child">
-              <dd><a lay-href="account/user_password.html">修改密码</a></dd>
-              <hr>
-              <dd layadmin-event="logout" style="text-align: center;"><a>退出</a></dd>
-            </dl>
-          </li>
 
-          <li class="layui-nav-item layui-hide-xs" lay-unselect>
-            <a href="javascript:;" layadmin-event="about"><i class="layui-icon layui-icon-more-vertical"></i></a>
-          </li>
-          <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-unselect>
-            <a href="javascript:;" layadmin-event="more"><i class="layui-icon layui-icon-more-vertical"></i></a>
-          </li>
-        </ul>
-      </div>
-      
-      <!-- 侧边菜单 -->
-      <div class="layui-side layui-side-menu">
-        <div class="layui-side-scroll">
-          <div class="layui-logo">
-            <span>小程序商城<span style="font-size: 12px;">erp</span></span>
-          </div>
+<div id="LAY_app">
+    <div class="layui-layout layui-layout-admin">
+        <div class="layui-header">
+            <!-- 头部区域 -->
+            <ul class="layui-nav layui-layout-left">
+                <li class="layui-nav-item layadmin-flexible" lay-unselect>
+                    <a href="javascript:;" layadmin-event="flexible" title="侧边伸缩">
+                        <i class="layui-icon layui-icon-shrink-right" id="LAY_app_flexible"></i>
+                    </a>
+                </li>
+                <li class="layui-nav-item" lay-unselect>
+                    <a href="javascript:;" layadmin-event="refresh" title="刷新">
+                        <i class="layui-icon layui-icon-refresh-3"></i>
+                    </a>
+                </li>
+            </ul>
+            <ul class="layui-nav layui-layout-right" lay-filter="layadmin-layout-right">
+                <li class="layui-nav-item layui-hide-xs" lay-unselect>
+                    <a href="javascript:;" layadmin-event="theme">
+                        <i class="layui-icon layui-icon-theme"></i>
+                    </a>
+                </li>
+                <li class="layui-nav-item" lay-unselect>
+                    <a href="javascript:;">
+                        <cite id="id_username"></cite>
+                    </a>
+                    <dl class="layui-nav-child">
+                        <dd><a lay-href="account/user_password.html">修改密码</a></dd>
+                        <hr>
+                        <dd layadmin-event="logout" style="text-align: center;"><a>退出</a></dd>
+                    </dl>
+                </li>
 
-          <ul class="layui-nav layui-nav-tree" lay-shrink="all" id="LAY-system-side-muen" lay-filter="layadmin-system-side-menu">
-            <li data-name="set" class="layui-nav-item">
-              <a href="javascript:;" lay-tips="公告管理" lay-direction="2">
-                <i class="layui-icon layui-icon-notice"></i>
-                <cite>公告管理</cite>
-              </a>
-              <dl class="layui-nav-child">
-                <dd data-name="button">
-                  <a lay-href="notice/notice.html">公告管理</a>
-                </dd>
-              </dl>
-            </li>
-            <li data-name="set" class="layui-nav-item">
-              <a href="javascript:;" lay-tips="销售管理" lay-direction="2">
-                <i class="layui-icon layui-icon-form"></i>
-                <cite>销售管理</cite>
-              </a>
-              <dl class="layui-nav-child">
-                <dd data-name="button">
-                  <a lay-href="plan/sale.html">销售计划管理</a>
-                </dd>
-                <dd data-name="button">
-                  <a lay-href="order/sale_order.html">销售订单管理</a>
-                </dd>
-                <dd data-name="button" >
-                  <a lay-href="goods/goods_stock_query.html">成品库存查询</a>
-                </dd>
-              </dl>
-            </li>
-            <li data-name="component" class="layui-nav-item">
-              <a href="javascript:;" lay-tips="生产管理" lay-direction="2">
-                <i class="layui-icon layui-icon-read"></i>
-                <cite>生产管理</cite>
-              </a>
-              <dl class="layui-nav-child">
-                <dd data-name="nav" >
-                  <a lay-href="plan/production.html">生产计划管理</a>
-                </dd>
-              </dl>
-            </li>
-            <li data-name="set" class="layui-nav-item">
-              <a href="javascript:;" lay-tips="采购管理" lay-direction="2">
-                <i class="layui-icon layui-icon-cart-simple"></i>
-                <cite>采购管理</cite>
-              </a>
-              <dl class="layui-nav-child">
-                <dd data-name="button">
-                  <a lay-href="purchase/purchase.html">计划管理</a>
-                </dd>
-                <dd data-name="button">
-                  <a lay-href="purchase/purchase_price.html">询价管理</a>
-                </dd>
-                <dd data-name="button">
-                    <a lay-href="purchase/purchase_order.html">合同管理</a>
-                  </dd>
-                <dd data-name="button">
-                    <a lay-href="purchase/purchase_payment.html">付款管理</a>
-                  </dd>
-                <dd data-name="button">
-                    <a lay-href="purchase/purchase_invoice.html">发票管理</a>
-                  </dd>
-                <dd data-name="button" >
-                    <a lay-href="purchase/purchase_price_query.html">询价历史</a>
-                  </dd>
-              </dl>
-            </li>
-            <li data-name="set" class="layui-nav-item">
-              <a href="javascript:;" lay-tips="基础数据" lay-direction="2">
-                <i class="layui-icon layui-icon-set"></i>
-                <cite>基础数据</cite>
-              </a>
-              <dl class="layui-nav-child">
-                <dd data-name="nav">
-                  <a lay-href="usedvehicle/index.html">二手车档案</a>
-                </dd>
-                <dd data-name="nav">
-                  <a lay-href="option/index.html">系统选项</a>
-                </dd>
-                <dd data-name="nav">
-                  <a lay-href="customer/customer.html">客户管理</a>
-                </dd>
-                <dd data-name="nav">
-                  <a lay-href="account/employee.html">人员管理</a>
-                </dd>
-                <dd data-name="nav">
-                  <a lay-href="config/index.html">基础设置</a>
-                </dd>
-              </dl>
-            </li>
-          </ul>
+                <li class="layui-nav-item layui-hide-xs" lay-unselect>
+                    <a href="javascript:;" layadmin-event="about"><i
+                            class="layui-icon layui-icon-more-vertical"></i></a>
+                </li>
+                <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-unselect>
+                    <a href="javascript:;" layadmin-event="more"><i class="layui-icon layui-icon-more-vertical"></i></a>
+                </li>
+            </ul>
         </div>
-      </div>
 
-      <!-- 页面标签 -->
-      <div class="layadmin-pagetabs" id="LAY_app_tabs">
-        <div class="layui-icon layadmin-tabs-control layui-icon-prev" layadmin-event="leftPage"></div>
-        <div class="layui-icon layadmin-tabs-control layui-icon-next" layadmin-event="rightPage"></div>
-        <div class="layui-icon layadmin-tabs-control layui-icon-down">
-          <ul class="layui-nav layadmin-tabs-select" lay-filter="layadmin-pagetabs-nav">
-            <li class="layui-nav-item" lay-unselect>
-              <a href="javascript:;"></a>
-              <dl class="layui-nav-child layui-anim-fadein">
-                <dd layadmin-event="closeThisTabs"><a href="javascript:;">关闭当前标签页</a></dd>
-                <dd layadmin-event="closeOtherTabs"><a href="javascript:;">关闭其它标签页</a></dd>
-                <dd layadmin-event="closeAllTabs"><a href="javascript:;">关闭全部标签页</a></dd>
-              </dl>
-            </li>
-          </ul>
+        <!-- 侧边菜单 -->
+        <div class="layui-side layui-side-menu">
+            <div class="layui-side-scroll">
+                <div class="layui-logo">
+                    <span>小程序商城<span style="font-size: 12px;">erp</span></span>
+                </div>
+
+                <ul class="layui-nav layui-nav-tree" lay-shrink="all" id="LAY-system-side-muen"
+                    lay-filter="layadmin-system-side-menu">
+                    <li data-name="set" class="layui-nav-item">
+                        <a href="javascript:;" lay-tips="公告管理" lay-direction="2">
+                            <i class="layui-icon layui-icon-notice"></i>
+                            <cite>公告管理</cite>
+                        </a>
+                        <dl class="layui-nav-child">
+                            <dd data-name="button">
+                                <a lay-href="notice/notice.html">公告管理</a>
+                            </dd>
+                        </dl>
+                    </li>
+                    <li data-name="set" class="layui-nav-item">
+                        <a href="javascript:;" lay-tips="销售管理" lay-direction="2">
+                            <i class="layui-icon layui-icon-form"></i>
+                            <cite>销售管理</cite>
+                        </a>
+                        <dl class="layui-nav-child">
+                            <dd data-name="button">
+                                <a lay-href="plan/sale.html">销售计划管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="order/sale_order.html">销售订单管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="goods/goods_stock_query.html">成品库存查询</a>
+                            </dd>
+                        </dl>
+                    </li>
+                    <li data-name="component" class="layui-nav-item">
+                        <a href="javascript:;" lay-tips="生产管理" lay-direction="2">
+                            <i class="layui-icon layui-icon-read"></i>
+                            <cite>生产管理</cite>
+                        </a>
+                        <dl class="layui-nav-child">
+                            <dd data-name="nav">
+                                <a lay-href="plan/production.html">生产计划管理</a>
+                            </dd>
+                        </dl>
+                    </li>
+                    <li data-name="set" class="layui-nav-item">
+                        <a href="javascript:;" lay-tips="采购管理" lay-direction="2">
+                            <i class="layui-icon layui-icon-cart-simple"></i>
+                            <cite>采购管理</cite>
+                        </a>
+                        <dl class="layui-nav-child">
+                            <dd data-name="button">
+                                <a lay-href="purchase/purchase.html">计划管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="purchase/purchase_price.html">询价管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="purchase/purchase_order.html">合同管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="purchase/purchase_payment.html">付款管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="purchase/purchase_invoice.html">发票管理</a>
+                            </dd>
+                            <dd data-name="button">
+                                <a lay-href="purchase/purchase_price_query.html">询价历史</a>
+                            </dd>
+                        </dl>
+                    </li>
+                    <li data-name="set" class="layui-nav-item">
+                        <a href="javascript:;" lay-tips="基础数据" lay-direction="2">
+                            <i class="layui-icon layui-icon-set"></i>
+                            <cite>基础数据</cite>
+                        </a>
+                        <dl class="layui-nav-child">
+                            <dd data-name="nav" data-permission="vehicle_model.browse_vehicle_series">
+                                <a lay-href="vehicle_series/index.html">车系管理</a>
+                            </dd>
+                            <dd data-name="nav" data-permission="vehicle_model.browse_vehicle_model">
+                                <a lay-href="vehicle_model/index.html">车型管理</a>
+                            </dd>
+                            <dd data-name="nav">
+                                <a lay-href="usedvehicle/index.html">二手车档案</a>
+                            </dd>
+                            <dd data-name="nav">
+                                <a lay-href="option/index.html">系统选项</a>
+                            </dd>
+                            <dd data-name="nav">
+                                <a lay-href="customer/customer.html">客户管理</a>
+                            </dd>
+                            <dd data-name="nav">
+                                <a lay-href="account/employee.html">人员管理</a>
+                            </dd>
+                            <dd data-name="nav">
+                                <a lay-href="config/index.html">基础设置</a>
+                            </dd>
+                        </dl>
+                    </li>
+                </ul>
+            </div>
         </div>
-        <div class="layui-tab" lay-unauto lay-allowClose="true" lay-filter="layadmin-layout-tabs">
-          <ul class="layui-tab-title" id="LAY_app_tabsheader">
-            <li lay-id="home/console.html" class="layui-this"><i class="layui-icon layui-icon-home"></i></li>
-          </ul>
+
+        <!-- 页面标签 -->
+        <div class="layadmin-pagetabs" id="LAY_app_tabs">
+            <div class="layui-icon layadmin-tabs-control layui-icon-prev" layadmin-event="leftPage"></div>
+            <div class="layui-icon layadmin-tabs-control layui-icon-next" layadmin-event="rightPage"></div>
+            <div class="layui-icon layadmin-tabs-control layui-icon-down">
+                <ul class="layui-nav layadmin-tabs-select" lay-filter="layadmin-pagetabs-nav">
+                    <li class="layui-nav-item" lay-unselect>
+                        <a href="javascript:;"></a>
+                        <dl class="layui-nav-child layui-anim-fadein">
+                            <dd layadmin-event="closeThisTabs"><a href="javascript:;">关闭当前标签页</a></dd>
+                            <dd layadmin-event="closeOtherTabs"><a href="javascript:;">关闭其它标签页</a></dd>
+                            <dd layadmin-event="closeAllTabs"><a href="javascript:;">关闭全部标签页</a></dd>
+                        </dl>
+                    </li>
+                </ul>
+            </div>
+            <div class="layui-tab" lay-unauto lay-allowClose="true" lay-filter="layadmin-layout-tabs">
+                <ul class="layui-tab-title" id="LAY_app_tabsheader">
+                    <li lay-id="home/console.html" class="layui-this"><i class="layui-icon layui-icon-home"></i></li>
+                </ul>
+            </div>
         </div>
-      </div>
-      
-      
-      <!-- 主体内容 -->
-      <div class="layui-body" id="LAY_app_body">
-        <div class="layadmin-tabsbody-item layui-show">
-          <iframe src="dashboard/home.html" frameborder="0" class="layadmin-iframe"></iframe>
+
+
+        <!-- 主体内容 -->
+        <div class="layui-body" id="LAY_app_body">
+            <div class="layadmin-tabsbody-item layui-show">
+                <iframe src="dashboard/home.html" frameborder="0" class="layadmin-iframe"></iframe>
+            </div>
         </div>
-      </div>
-      
-      <!-- 辅助元素,一般用于移动设备下遮罩 -->
-      <div class="layadmin-body-shade" layadmin-event="shade"></div>
+
+        <!-- 辅助元素,一般用于移动设备下遮罩 -->
+        <div class="layadmin-body-shade" layadmin-event="shade"></div>
     </div>
-  </div>
+</div>
 
-  <script src="../layuiadmin/layui/layui.js"></script>
-  <script>
-  layui.config({
-    base: '../layuiadmin/' //静态资源所在路径
-  }).extend({
-    index: 'lib/index' //主入口模块
-  }).use('index', function () {
-      var $ = layui.$;
-      var name = layui.data(layui.setter.tableName)['name'];
-      $('#id_username').html(name);
+<script src="../layuiadmin/layui/layui.js"></script>
+<script>
+    layui.config({
+        base: '../layuiadmin/' //静态资源所在路径
+    }).extend({
+        index: 'lib/index' //主入口模块
+    }).use('index', function () {
+        var $ = layui.$;
+        var name = layui.data(layui.setter.tableName)['name'];
+        $('#id_username').html(name);
 
-  });
-  </script>
+    });
+</script>
 </body>
 </html>
 

+ 185 - 0
uis/views/vehicle_model/details.html

@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>成品产品管理</title>
+    <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+</head>
+<body>
+    <div class="layui-fluid">
+        <div class="layui-card">
+            <div class="layui-card-body" pad15>
+               <div class="layui-tab layui-tab-card">
+                   <ul class="layui-tab-title">
+                       <li class="layui-this">车型信息</li>
+                       <li>海报信息</li>
+                       <li>整车图片</li>
+                       <li>车型图片</li>
+                       <li>车型规格</li>
+                   </ul>
+                   <div class="layui-tab-content">
+                       <div class="layui-tab-item layui-show">
+                           <table class="layui-table">
+                               <tr>
+                                   <th style="width: 100px;">品牌名称</th>
+                                   <td id="brand_name" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">车系名称</th>
+                                   <td id="series_name" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">车型名称</th>
+                                   <td id="name" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">定金金额</th>
+                                   <td id="advance_pay_show" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">顶现金额</th>
+                                   <td id="equal_pay_show" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">指导价格</th>
+                                   <td id="price_show" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">本店价格</th>
+                                   <td id="shop_price_show" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">车型介绍</th>
+                                   <td id="describe" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">是否热门</th>
+                                   <td id="hot_text" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">推荐数</th>
+                                   <td id="recommend_count" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">成交数</th>
+                                   <td id="success_count" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">收藏数</th>
+                                   <td id="collection_count" class="cell"></td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">车型图片</th>
+                                   <td>
+                                       <img class="layui-upload-img" id="thumbnail" style="max-height: 250px;">
+                                   </td>
+                               </tr>
+                               <tr>
+                                   <th style="width: 100px;">备注</th>
+                                   <td id="notes" class="cell"></td>
+                               </tr>
+                           </table>
+                       </div>
+                       <div class="layui-tab-item">
+                           <img class="layui-upload-img" id="playbill" style="max-height: 250px;">
+                       </div>
+                       <div class="layui-tab-item">
+                           <div class="layui-upload-list" id="images" style="display: flex;flex-wrap: wrap;">
+                           </div>
+                       </div>
+                       <div class="layui-tab-item">
+                           <div class="layui-upload" id="div_upload">
+                           </div>
+                       </div>
+                       <div class="layui-tab-item">
+                           <table class="layui-hide" id="datagrid"></table>
+                       </div>
+                   </div>
+               </div>
+            </div>
+        </div>
+    </div>
+
+    <script src="../../layuiadmin/layui/layui.js?t=1"></script>
+    <script>
+        layui.config({
+            base: '../../../layuiadmin/' //静态资源所在路径
+        }).extend({
+            index: 'lib/index' //主入口模块
+        }).use(['index', 'table','laydate', 'utils'], function () {
+            var $ = layui.$;
+            var table = layui.table;
+            var admin = layui.admin;
+            var options = null;
+
+            var id = layui.view.getParameterByName('id');
+            var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata));
+            $('#thumbnail').attr('src', editdata.thumbnail_url);
+            $('#playbill').attr('src', editdata.playbill_url);
+            $('.cell').each(function (index, element) {
+                element.innerHTML =  (editdata[element.id])
+            });
+
+            admin.req({
+                 url: '/vehicle/images/?vehicle_model=' + id,
+                done: function (res) {
+                   $('#images').html('');
+                   var data = res.data;
+                   for (var i in data){
+                       var html = '<div style="margin-top: 10px;"><a href="'+data[i].img_url+'" target="_blank"><img src="'+ data[i].img_url +'" class="layui-upload-img" style="margin-left: 5px;min-width: 80px; height: 100px;max-width: 200px;"></a></div>';
+                        $('#images').append(html)
+                   }
+                }
+             });
+
+            admin.req({
+                 url: '/option/search/?type=3'
+                 ,done: function(res){
+                     var data = res.data;
+                     options = res.data;
+                     for (var m in data){
+                         var div_id='show_image_'+data[m].id;
+                         var html  = '<span >'+data[m].name+'图片</span>' +
+                         '<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">' +
+                         '<div class="layui-upload-list" id="'+div_id+'" style="display: flex;flex-wrap: wrap;"></div></blockquote>';
+                         $('#div_upload').append(html)
+                     }
+                     loadUpload();
+                 }
+            });
+
+            var loadUpload = function(){
+                admin.req({
+                     url: '/vehicle/model_images/?vehicle_model=' + id,
+                    done: function (res) {
+                       for (var i in options){
+                          $('#show_image_' + options[i].id).html('');
+                        }
+
+                       var data = res.data;
+                       for (var i in data){
+                           var html = '<div style="margin-top: 10px;"><a href="'+data[i].img_url+'" target="_blank"><img src="'+ data[i].img_url +'" class="layui-upload-img" style="margin-left: 5px;min-width: 80px; height: 100px;max-width: 200px;"></a></div>';
+                            $('#show_image_'+ data[i].type).append(html)
+                       }
+                    }
+                 });
+            };
+
+            table.render({
+              elem: '#datagrid'
+              ,url: '/vehicle/model_specs/?vehicle_model=' + id
+              ,cols: [[
+                {field:'name_text', title:'名称',width: 150}
+               ,{field:'value', title:'值',width: 100}
+               ,{field:'notes', title:'备注',width: 200}
+              ]]
+              ,height: 'full-108'
+            });
+        })
+    </script>
+</body>
+</html>

+ 304 - 0
uis/views/vehicle_model/edit.html

@@ -0,0 +1,304 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>添加员工信息</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+  <link rel="stylesheet" type="text/css" href="../../layuiadmin/style/formSelects-v4.css"/>
+    <link rel="stylesheet" type="text/css" href="../../layuiadmin/layui/ueditor/themes/default/css/umeditor.css"/>
+    <script type="text/javascript" src="../../layuiadmin/layui/ueditor/third-party/jquery.min.js"></script>
+    <script type="text/javascript" charset="utf-8" src="../../layuiadmin/layui/ueditor/umeditor.config.js"></script>
+    <script type="text/javascript" charset="utf-8" src="../../layuiadmin/layui/ueditor/umeditor.js"></script>
+    <script type="text/javascript" src="../../layuiadmin/layui/ueditor/lang/zh-cn/zh-cn.js"></script>
+    <style>
+        .xm-select-parent .xm-form-selected dl {
+            height: 160px;
+        }
+    </style>
+</head>
+<body>
+
+  <div class="layui-fluid">
+        <div class="layui-card">
+          <div class="layui-card-body" pad15>
+            <form class="layui-form" action="" lay-filter="component-form-element">
+              <div class="layui-row layui-col-space10 layui-form-item">
+                <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>车系:</label>
+                  <div class="layui-input-block">
+                       <input id="id_series" name="series" class="layui-input" autocomplete="off" lay-verify="required"/>
+                  </div>
+                </div>
+                <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>名称:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="name" lay-verify="required" placeholder="请输入名称" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>定金:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="advance_pay_show" placeholder="请输入定金" lay-verify="required|numberGtZ" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                 <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>顶现金额:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="equal_pay_show" placeholder="请输入顶现金额" lay-verify="required|numberGtZ" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>指导价:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="price_show" lay-verify="required|numberGtZ" placeholder="请输入指导价" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>本店价格:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="shop_price_show" lay-verify="required|numberGtZ" placeholder="请输入本店价格" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                <div>
+                    <label class="layui-form-label">车型标签:</label>
+                    <div class="layui-input-block">
+                      <select name="tags" xm-select="manager_tags"></select>
+                    </div>
+                </div>
+                <div>
+                  <label class="layui-form-label">提成金额:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="commission_amount" placeholder="请输入提成金额" lay-verify="numberGeZ" autocomplete="off" class="layui-input">
+                    <div class="layui-word-aux" ><span style="color: red;">佣金=提成金额</span></div>
+                  </div>
+                </div>
+                <div>
+                  <label class="layui-form-label">排序:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="sort" placeholder="请输入排序" lay-verify="numberGez"  autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+
+                <div >
+                  <label class="layui-form-label">在用:</label>
+                  <div class="layui-input-block">
+                    <input type="checkbox" name="enabled" lay-skin="switch" lay-text="是|否" checked="" value="1">
+                  </div>
+                </div>
+                <div >
+                  <label class="layui-form-label">热门:</label>
+                  <div class="layui-input-block">
+                      <input id="id_checked" type="checkbox" name="is_hot" lay-skin="switch" lay-text="是|否" checked="">
+                  </div>
+                </div>
+                <div>
+                <label class="layui-form-label"><font color='red' size="4">*</font>车型介绍:</label>
+                  <div class="layui-input-block">
+                      <script type="text/plain" id="myEditor"></script>
+                  </div>
+                </div>
+                <div>
+                  <label class="layui-form-label">备注:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="notes" placeholder="请输入备注" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+               <div>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>车型图片:</label>
+                  <div class="layui-input-block">
+                      <button type="button" class="layui-btn-sm" id="test1">上传图片</button><br><br>
+                      <img class="layui-upload-img" id="demo1" style="max-width: 300px; max-height: 200px;">
+                  </div>
+                </div>
+                <button class="layui-btn" id="id_save" lay-submit lay-filter="component-form-element" style="display: none">保存</button>
+                  <button class="layui-btn" type="button" id="upload_image" style="display: none"></button>
+              </div>
+            </form>
+          </div>
+        </div>
+  </div>
+
+
+  <script src="../../layuiadmin/layui/layui.js"></script>
+  <script>
+  layui.link('../../../layuiadmin/style/autocomplete.css');
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+
+  }).extend({
+    index: 'lib/index',
+    formSelects: 'formSelects-v4',
+    autocomplete: 'autocomplete'
+  }).use(['index', 'form', 'utils', 'upload', 'autocomplete', 'formSelects'], function(){
+    var $ = layui.$
+    ,admin = layui.admin
+    ,upload = layui.upload
+    ,autocomplete = layui.autocomplete
+    ,formSelects = layui.formSelects
+    ,form = layui.form;
+    var id = layui.view.getParameterByName('id');
+    var series = null;
+
+    if (!id || id === '') {
+        $('#id_checked').removeAttr('checked');
+    }
+
+    var um = UM.getEditor('myEditor');
+    um.setWidth('100%');
+    $(".edui-body-container").css("width", "98%");
+
+    autocomplete.render({
+        elem:$('#id_series'),
+        url:'/vehicle/series/search/',
+        template_val:'',
+        template_txt:'<span class=\'layui-badge layui-bg-gray\'>{{d.brand_name}} - {{d.name}}',
+        onselect: function (resp) {
+            $('#id_series').val(resp.brand_name + '-' + resp.name);
+            series = resp.id;
+        }
+    });
+
+
+    formSelects.value('manager_tags', []);
+    admin.req({
+        url: '/option/search/?type=2'
+        ,done: function(res){
+            var _nodes = res.data;
+            formSelects.data('manager_tags', 'local', {
+            arr: _nodes,
+            tree: {
+                //在点击节点的时候, 如果没有子级数据, 会触发此事件
+                nextClick: function(id, item, callback){
+                    return false;
+                    },
+                }
+            });
+            //formSelects.value('manager_range', manages);
+            loadData();
+        }
+    });
+
+    var loadData = function () {
+        if(id){
+            var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
+            form.val("component-form-element", editdata);
+            $('#id_series').val(editdata.brand_name + '-' + editdata.series_name);
+            series = editdata.series;
+            formSelects.value('manager_tags', editdata.tags);
+            um.setContent(editdata.describe);
+            if(editdata.thumbnail_url){
+                $('#demo1').attr('src', editdata.thumbnail_url);
+            }
+        }
+    };
+
+
+    form.render(null, 'component-form-element');
+
+    var form_data = {field:{}};
+    if (id){
+          var url = '/vehicle/model/' +id + '/update_model/';
+      }else{
+          url =  '/vehicle/model/';
+      }
+    upload.render({
+         elem: '#test1',
+         url: url,
+         auto: false,
+         field: 'image',
+         bindAction: '#upload_image',
+         choose: function(obj) {
+             obj.preview(
+                 function(index, file, result) {
+                     $('#demo1').attr('src', result);
+                 }
+             );
+         },
+         data:{
+             series: function(){return form_data.field.series;},
+             name: function(){return form_data.field.name;},
+             price: function(){return form_data.field.price_show;},
+             shop_price: function(){return form_data.field.shop_price_show},
+             advance_pay: function(){return form_data.field.advance_pay_show;},
+             equal_pay: function(){return form_data.field.equal_pay_show;},
+             notes: function(){return form_data.field.notes;},
+             describe: function(){return form_data.field.describe;},
+             tags: function(){return form_data.field.tags;},
+             commission_ratio: function(){return form_data.field.commission_amount;},
+             sort: function(){return form_data.field.sort;},
+             enabled: function(){
+                 if (form_data.field.enabled){
+                     return form_data.field.enabled;
+                 }else{
+                     return '0';
+                 }
+             },
+             is_hot: function(){
+                 if (form_data.field.is_hot){
+                     return form_data.field.is_hot;
+                 }else{
+                     return '0';
+                 }
+             }
+             },
+        done: function (res) {
+            if (res.code != 0) {
+                layer.msg(res.msg);
+            }else {
+                parent.layui.onSubmitChild(res.data);
+            }
+        },
+        error: function () {
+            layer.msg('保存失败');
+        }
+    });
+
+    form.on('submit(component-form-element)', function (data) {
+        if (!series){
+            layer.msg('请搜索并选择车型');
+            return false;
+        }
+        //console.log('000000000000000000000000000000');
+        //console.log(JSON.stringify(data.field));
+
+        if (!id && !data.field.image) {
+            layer.msg('车型图片是必填项',{icon: 5});
+            return false;
+        }
+
+        var describe = UM.getEditor('myEditor').getContent();
+        data.field['describe'] = describe;
+        data.field['series'] = series;
+        if (data.field.image){
+            form_data = data;
+            $('#upload_image').click();
+        }else{
+            var save_data = data.field;
+            save_data['price'] = data.field.price_show;
+            save_data['shop_price'] = data.field.shop_price_show;
+            save_data['advance_pay'] = data.field.advance_pay_show;
+            save_data['equal_pay'] = data.field.equal_pay_show;
+            save_data['commission_ratio'] = data.field.commission_amount;
+            admin.req({
+                url: url
+                ,data: data.field
+                ,type: 'post'
+                ,done: function(res){
+                    parent.layui.onSubmitChild(res.data);
+                }
+              });
+        }
+        return false;
+    });
+
+    parent.layui.submitChild = function () {
+      $("#id_save").click();
+    };
+  });
+  </script>
+</body>
+</html>

+ 279 - 0
uis/views/vehicle_model/index.html

@@ -0,0 +1,279 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>人员管理</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+  <link rel="stylesheet" type="text/css" href="../../layuiadmin/style/formSelects-v4.css"/>
+    <style type="text/css">
+    .LAY-btns .layui-nav {padding-left:0;padding-right:10px;top:-4px;margin: 0 10px;border: 0;background-color: #009688;}
+    .LAY-btns .layui-nav .layui-nav-item{line-height: 30px;}
+    .LAY-btns .layui-nav .layui-nav-child{top:34px;}
+    .LAY-btns .layui-nav .layui-nav-bar{display: none;}
+    .LAY-btns .layui-nav .layui-nav-child dd.layui-this a{color:#333;background-color:#fff;}
+    .LAY-btns .layui-nav .layui-nav-child dd.layui-this a:hover {background-color: #f2f2f2;color: #000;}
+    .seach_items {float:right;margin-left: 10px;}
+  </style>
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body" pad15>
+        <div class="layui-row layui-col-space15">
+          <div class="layui-col-md12">
+            <div class="LAY-btns" style="margin-bottom: 10px;">
+                <div class="layui-col-xs2">
+                    <button class="layui-btn" id="btn_add"><i class="layui-icon layui-icon-add-circle"></i>添加</button>
+                </div>
+                <form class="layui-form" lay-filter="query-form-element">
+                    <div class="seach_items">
+                        <button class="layui-btn" lay-submit lay-filter="query-form-element"><i class="layui-icon layui-icon-search"></i>查询</button>
+                    </div>
+
+                    <div class="seach_items">
+                        <input type="text"  name="name" autocomplete="off" class="layui-input" placeholder="名称"/>
+                    </div>
+
+                    <div class="seach_items">
+                        <input type="text"  name="series_name" autocomplete="off" class="layui-input" placeholder="车系名称"/>
+                    </div>
+                    <div class="seach_items">
+                         <input type="text"  name="brand_name" autocomplete="off" class="layui-input" placeholder="品牌名称"/>
+                    </div>
+                </form>
+                <div style="clear: both;"></div>
+            </div>
+            <table class="layui-hide" id="datagrid" lay-filter="datagrid-operate"></table>
+
+            <script type="text/html" id="datagrid-operate-bar">
+                <div class="layui-btn-group">
+                    <a class="layui-btn layui-btn-xs" lay-event="detail">查看</a>
+                    <a class="layui-btn layui-btn-xs" lay-event="edit" >修改</a>
+                    <a class="layui-btn layui-btn-xs" lay-event="upload_poster" >海报</a>
+                    <a class="layui-btn layui-btn-xs" lay-event="upload" >整车图片</a>
+                    <a class="layui-btn layui-btn-xs" lay-event="model_upload" >车型图片</a>
+                    <a class="layui-btn layui-btn-xs" lay-event="specs" >规格</a>
+                    <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del" >删除</a>
+                </div>
+            </script>
+          </div>
+        </div>
+        </div>
+    </div>
+  </div>
+
+  <script src="../../layuiadmin/layui/layui.js?t=1"></script>
+  <script>
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index' //主入口模块
+     ,formSelects: 'formSelects-v4'
+  }).use(['index', 'table', 'form', 'formSelects', 'upload'], function(){
+    var $ = layui.$
+            ,table = layui.table
+            ,admin = layui.admin
+            ,form = layui.form;
+
+    admin.req({
+        url: '/vehicle/dict/',
+        done: function (res) {
+            var brands = res.data.brand;
+            var brand_node = $('#id_brand');
+            for (var i in brands) {
+                var pid = brands[i].id;
+                var value = brands[i].name;
+                brand_node.append("<option value='" + pid + "'>" + value + "</option>");
+            }
+
+            var series = res.data.series;
+            var series_node = $('#id_series');
+            for (var i in series) {
+                var pid = series[i].id;
+                var value = series[i].name;
+                series_node.append("<option value='" + pid + "'>" + value + "</option>");
+            }
+
+            form.render();
+        }
+    });
+
+
+    table.render({
+      elem: '#datagrid'
+      ,url: '/vehicle/model/'
+      ,cols: [[
+        {field:'brand_name', title:'品牌',width: 100}
+        ,{field:'series_name', title:'车系',width: 200}
+       ,{field:'name', title:'车型',width: 200}
+       ,{field:'advance_pay_show', align:'right', title:'定金',width: 100}
+       ,{field:'equal_pay_show', align:'right', title:'顶现金额',width: 100}
+       ,{field:'price_show', align:'right', title:'指导价',width: 150}
+       ,{field:'shop_price_show', align:'right', title:'本店价格',width: 150}
+       ,{field:'commission_amount', align:'right', title:'提成金额',width: 100}
+       ,{field:'sort', title:'排序', width:70}
+       ,{field:'enabled_text', title:'在用',width: 70}
+       ,{field:'hot_text', title:'热门',width: 70}
+       ,{field:'recommend_count', align:'right', title:'推荐数',width: 80}
+       ,{field:'success_count', align:'right', title:'成交数',width: 80}
+       ,{field:'collection_count', align:'right', title:'收藏数',width: 80}
+        ,{field:'notes', title:'备注'}
+        ,{width:330, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
+      ]]
+      ,page: true
+      ,height: 'full-108'
+      , done: function () {
+        layui.index.removeNoPermButtons()
+      }
+    });
+    form.on('submit(query-form-element)', function(data){
+      //layer.msg(JSON.stringify(data.field));
+      table.reload('datagrid', {
+          where: data.field
+          ,page:{curr:1}
+      });
+      layer.closeAll();
+      return false;
+    });
+    //监听工具条
+    table.on('tool(datagrid-operate)', function(obj){
+      var data = obj.data;
+      table.editdata = data;
+        if(obj.event === 'edit'){
+        layer.open({
+          type: 2,
+          title: '修改',
+          shadeClose: false,
+          area: ['70%', '90%'],
+          btn: ['保存', '取消'],
+          yes: function (index, dom) {
+            layui.onSubmitChild = function (data) {
+                layer.close(index);
+                table.reload('datagrid', {});
+              };
+              layui.submitChild();
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'edit.html?id='+data.id
+        });
+      }else if(obj.event === 'detail'){
+        layer.open({
+          type: 2,
+          title: '查看',
+          shadeClose: true,
+          area: ['70%', '90%'],
+          content: 'details.html?id='+data.id
+        });
+      }else if(obj.event === 'del'){
+         layer.confirm('确定要删除吗?', function(index){
+                layer.close(index);
+                layui.admin.req({
+                    notice: true
+                    ,url: '/vehicle/model/'+data.id + '/'
+                    ,type: 'delete'
+                    ,done: function(res){
+                        table.reload('datagrid',{});
+                    }
+                });
+            });
+      }else if(obj.event === 'upload'){
+        layer.open({
+          type: 2,
+          title: '上传',
+          area: ['800px', '500px'],
+          btn: ['完成', '取消'],
+          yes: function(index, dom){
+              table.reload('datagrid',{});
+             layer.close(index);
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'upload.html?id='+data.id
+        });
+      }else if(obj.event === 'upload_poster'){
+        layer.open({
+          type: 2,
+          title: '上传海报',
+          area: ['600px', '450px'],
+          btn: ['保存', '取消'],
+          yes: function(index, dom){
+            layui.onSubmitChild = function (data) {
+              layer.close(index);
+              table.reload('datagrid',{});
+            };
+            layui.submitChild();
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'upload_poster.html?id='+data.id
+        });
+      }else if (obj.event === 'specs'){
+            layer.open({
+              type: 2,
+              title: '设置规格参数',
+              area: ['70%', '500px'],
+              btn: ['保存', '取消'],
+              yes: function(index, dom){
+                 layui.onSubmitChild = function (data) {
+                  layer.close(index);
+                  table.reload('datagrid',{});
+                };
+                layui.submitChild();
+              },
+              btn2: function(index, layero){
+                layer.close(index);//关闭当前按钮
+              },
+              content: 'specs.html?id='+data.id
+            });
+        }else if (obj.event === 'model_upload'){
+            layer.open({
+              type: 2,
+              title: '上传车型图片',
+              area: ['70%', '90%'],
+              btn: ['保存', '取消'],
+              yes: function(index, dom){
+                 table.reload('datagrid',{});
+                 layer.close(index);
+              },
+              btn2: function(index, layero){
+                layer.close(index);//关闭当前按钮
+              },
+              content: 'upload_model.html?id='+data.id
+            });
+        }
+    });
+
+    $('#btn_add').on('click', function(){
+        layer.open({
+          type: 2,
+          title: '添加',
+          shadeClose: false,
+          area: ['70%', '90%'],
+          btn: ['保存', '取消'],
+          yes: function (index, dom) {
+            layui.onSubmitChild = function (data) {
+                layer.close(index);
+                table.reload('datagrid', {});
+              };
+              layui.submitChild();
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'edit.html'
+        });
+    });
+  });
+  </script>
+</body>
+</html>
+

+ 213 - 0
uis/views/vehicle_model/specs.html

@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title></title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+   <style type="text/css">
+        .table-overlay .layui-table-body{overflow: visible;}
+        .table-overlay .layui-table-cell{height: auto; overflow: visible;}
+    </style>
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body" pad15>
+            <div class="layui-row layui-col-space15">
+                <div class="layui-col-md12">
+                    <form class="layui-form" action="" lay-filter="component-form-element">
+                        <fieldset class="layui-elem-field layui-field-title">
+                            <legend>规格参数<button type="button" id="btn-add" class="layui-btn layui-btn-primary layui-btn-sm"><i class="layui-icon"></i></button></legend>
+                        </fieldset>
+                            <div id="consumableDataTable" class="table-overlay">
+                                <table id="consumable_layTable" lay-filter="consumable_layTable" class="layui-hide"></table>
+                            </div>
+                        <button class="layui-btn" id="btn_save" lay-submit lay-filter="component-form-element" style="display: none">确定</button>
+                     </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script src="../../layuiadmin/layui/layui.js"></script>
+<script>
+layui.link('../../../layuiadmin/style/autocomplete.css');
+layui.config({
+    base: '../../../layuiadmin/', //静态资源所在路径
+     autocomplete: 'autocomplete'
+}).extend({
+    index: 'lib/index' //主入口模块
+}).use(['index', 'form', 'table', 'laydate', 'utils', 'autocomplete'], function() {
+    var $ = layui.$;
+    var admin = layui.admin;
+    var form = layui.form;
+    var table = layui.table;
+    var id = layui.view.getParameterByName('id');
+
+    var consumable_tbWidth = $("#consumableDataTable").width();
+    var consumable_layTable = "consumable_layTable";
+    var consumable_tableIns = table.render({
+        elem: '#consumable_layTable',
+        id: consumable_layTable,
+        data: [],
+        width: consumable_tbWidth,
+        page: false,
+        limit: 1000,
+        loading: true,
+        even: true, //不开启隔行背景
+        cols: [[
+            {title: '序号', type: 'numbers'},
+            {field: 'name', title: '名称', width: 100},
+            {field: 'value', title: '值', width: 300,  templet: function (d) {
+                    return '<input id="value' + d.num + '" value="' + d.value + '" type="text" lay-verify="required" autocomplete="off" class="layui-input">';
+                }},
+            {field: 'notes', title: '备注', width: 200},
+            {
+                field: 'id', minWidth: 80, title: '操作', templet: function (d) {
+                    return '<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del" lay-id="' + d.num + '"><i class="layui-icon layui-icon-delete"></i>删除</a>';
+                }
+            }
+        ]],
+    });
+
+    admin.req({
+        url: '/vehicle/model_specs/?vehicle_model=' + id,
+        done: function (res) {
+            var data = res.data;
+            var roldData = table.cache[consumable_layTable];
+            var k=0;
+            for (var i in data) {
+                k = k + 1;
+                var newRow = {
+                    id: data[i].name,
+                    name: data[i].name_text,
+                    notes: data[i].notes,
+                    value: data[i].value,
+                    num: k
+                };
+                roldData.push(newRow);
+            }
+            consumable_tableIns.reload({
+                data: roldData
+            });
+
+        }
+    });
+
+
+    table.on('tool(consumable_layTable)', function (obj) {
+        var data = obj.data;
+        var event = obj.event;
+        switch (event) {
+            case "del":
+                obj.del();
+                layer.msg('删除成功', {icon: 6});
+                break;
+        }
+    });
+
+    var getconsumableData = function () {
+        var rows = table.cache[consumable_layTable];
+        var data = [];
+        for (var n in rows) {
+            if (rows[n] == false) {
+                continue;
+            }
+            var value = $('#value'+rows[n].num).val();
+            var item = {
+                num: rows[n].num,
+                id: rows[n].id,
+                name: rows[n].name,
+                notes: rows[n].notes,
+                value: value
+            };
+            data.push(item);
+        }
+        return data;
+    };
+    form.on('submit(component-form-element)', function (data) {
+        var rows = table.cache[consumable_layTable];
+        var save_data = [];
+        for (var n in rows) {
+            if (rows[n] == false) {
+                continue;
+            }
+            var value = $('#value'+rows[n].num).val();
+            var item = {
+                key: rows[n].id,
+                value: value
+            };
+            save_data.push(item);
+        }
+        admin.req({
+            url: '/vehicle/model/' + id + '/set_specs/'
+            ,type: 'post'
+            , data: {data: JSON.stringify(save_data)}
+            , done: function (res) {
+                parent.layui.onSubmitChild(res.data);
+            }
+        });
+        return false;
+    });
+    $('#btn-add').on('click', function () {
+        layer.open({
+            type: 2,
+            title: '添加产品',
+            area: ['90%', '98%'],
+            btn: ['确定', '取消'],
+            yes: function (index, dom) {
+                layui.onSubmitChild = function (data) {
+                    if(data.length === 0) {
+                        layer.msg('请先选择记录!');
+                        return;
+                    }
+                    var oldData = getconsumableData();
+                    var k=0;
+                    if (oldData.length > 0){
+                        k = oldData[oldData.length-1].num;
+                    }
+                    for (var i in data) {
+                        for(var m in oldData){
+                            if(oldData[m].id === data[i].id){
+                                layer.msg('规格['+data[i].name+']已添加!', {icon: 5});
+                                return;
+                            }
+                        }
+                        k = k + 1;
+                        var newRow = {
+                            id: data[i].id,
+                            name: data[i].name,
+                            notes: data[i].notes,
+                            num: k,
+                            value:''
+                        };
+                        oldData.push(newRow);
+                    }
+                    consumable_tableIns.reload({
+                        data: oldData
+                    });
+
+                    layer.msg('添加成功!', {icon: 6});
+                };
+                layui.submitChild();
+            },
+            btn2: function (index, layero) {
+                layer.close(index);//关闭当前按钮
+            },
+            content: '../option/search.html'
+        });
+    });
+    parent.layui.submitChild = function () {
+      $("#btn_save").click();
+    };
+});
+
+  </script>
+</body>
+</html>

+ 113 - 0
uis/views/vehicle_model/upload.html

@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>配件出库</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+</head>
+<body>
+
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body" pad15>
+            <div class="layui-row layui-col-space15">
+                <div class="layui-col-md12">
+                    <form class="layui-form" action="" lay-filter="component-form-element">
+                        <div class="layui-upload">
+                          <button type="button" class="layui-btn" id="upload_image">上传图片</button>
+                          <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
+                            已上传图片:
+                            <div class="layui-upload-list" id="show_image" style="display: flex;flex-wrap: wrap;"></div>
+                         </blockquote>
+                        </div>
+
+                        <button class="layui-btn" id="upload_save" lay-submit lay-filter="component-form-element" style="display: none">开始上传</button>
+                    </form>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+  <script src="../../layuiadmin/layui/layui.js"></script>
+  <script>
+   var main_id = null;
+  layui.link('../../../layuiadmin/style/autocomplete.css');
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index',
+    autocomplete: 'autocomplete'
+  }).use(['index','utils', 'form', 'element', 'upload'], function(){
+    var $ = layui.$
+    ,admin = layui.admin
+    ,element = layui.element
+    ,form = layui.form
+    ,upload = layui.upload;
+
+    var id = layui.view.getParameterByName('id');
+    main_id = id;
+
+    form.render(null, 'component-form-element');
+    element.render('breadcrumb', 'breadcrumb');
+    refresh();
+
+    //多图片上传
+  upload.render({
+    elem: '#upload_image'
+    ,url:  '/vehicle/model/'+id+'/set_vehicle_img/'
+    ,field: 'images'
+    ,exts: 'jpg|png|jpeg|bmp'
+    ,acceptMime: '.jpg,.png,.jpeg,.bmp'
+    ,multiple: true
+    ,done: function (res) {
+        if (res.code != 0) {
+            layer.msg(res.msg);
+        }else {
+            refresh();
+        }
+    },
+    error: function () {
+        layer.msg('保存失败');
+    }
+  });
+    parent.layui.submitChild = function () {
+      $("#upload_save").click();
+    };
+  });
+
+  function refresh () {
+      var $ = layui.$;
+      layui.admin.req({
+        url: '/vehicle/images/?vehicle_model=' + main_id,
+        done: function (res) {
+           $('#show_image').html('');
+           var data = res.data;
+           for (var i in data){
+               var html = '<div style="margin-top: 10px;"><a href="'+data[i].img_url+'" target="_blank"><img src="'+ data[i].img_url +'" class="layui-upload-img" style="margin-left: 5px;min-width: 80px; height: 100px;max-width: 200px;"></a>' +
+                      '<div align="center" style="margin-top: 3px;" ><button type="button" class="layui-btn layui-btn-danger layui-btn-xs" onclick="delImage('+data[i].id+')">删除</button></div></div>';
+                $('#show_image').append(html)
+           }
+        }
+    });
+  }
+
+  function delImage(id) {
+
+      layui.admin.req({
+         url: '/vehicle/images/'+id + '/'
+         ,type: 'delete'
+         ,done: function(res){
+             refresh();
+         }
+      });
+  }
+
+  </script>
+</body>
+</html>

+ 132 - 0
uis/views/vehicle_model/upload_model.html

@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>配件出库</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+</head>
+<body>
+
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body" pad15>
+            <div class="layui-row layui-col-space15">
+                <div class="layui-col-md12">
+                    <form class="layui-form" action="" lay-filter="component-form-element">
+                        <div class="layui-upload" id="div_upload">
+                        </div>
+                        <button class="layui-btn" id="upload_save" lay-submit lay-filter="component-form-element" style="display: none">开始上传</button>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+  <script src="../../layuiadmin/layui/layui.js"></script>
+  <script>
+   var main_id = null;
+   var options = null;
+  layui.link('../../../layuiadmin/style/autocomplete.css');
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index',
+    autocomplete: 'autocomplete'
+  }).use(['index','utils', 'form', 'element', 'upload'], function(){
+    var $ = layui.$
+    ,admin = layui.admin
+    ,element = layui.element
+    ,form = layui.form
+    ,upload = layui.upload;
+
+    var id = layui.view.getParameterByName('id');
+    main_id = id;
+
+    form.render(null, 'component-form-element');
+    element.render('breadcrumb', 'breadcrumb');
+
+    admin.req({
+         url: '/option/search/?type=3'
+         ,done: function(res){
+             var data = res.data;
+             options = res.data;
+             for (var m in data){
+                 var button_id='upload_image_'+data[m].id;
+                 var div_id='show_image_'+data[m].id;
+                 var html  = '<button type="button" class="layui-btn" id="'+button_id+'">上传'+data[m].name+'图片</button>' +
+                         '<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">已上传图片:' +
+                         '<div class="layui-upload-list" id="'+div_id+'" style="display: flex;flex-wrap: wrap;"></div></blockquote>';
+                 $('#div_upload').append(html)
+             }
+             loadUpload();
+            refresh();
+         }
+    });
+    //refresh();
+
+    //多图片上传
+    var loadUpload = function () {
+        for (var i in options){
+          upload.render({
+            elem: '#upload_image_' + options[i].id
+            ,url:  '/vehicle/model/'+id+'/set_model_img/'
+            ,field: 'images'
+            ,exts: 'jpg|png|jpeg|bmp'
+            ,acceptMime: '.jpg,.png,.jpeg,.bmp'
+            ,multiple: true
+            ,data: {type: options[i].id}
+            ,done: function (res) {
+                if (res.code != 0) {
+                    layer.msg(res.msg);
+                }else{
+                    refresh();
+                }
+            },
+            error: function () {
+                layer.msg('保存失败');
+            }
+          });
+      }
+    };
+    parent.layui.submitChild = function () {
+      $("#upload_save").click();
+    };
+  });
+
+  function refresh () {
+      var $ = layui.$;
+
+      layui.admin.req({
+        url: '/vehicle/model_images/?vehicle_model=' + main_id,
+        done: function (res) {
+         for (var i in options){
+              $('#show_image_' + options[i].id).html('');
+          }
+           var data = res.data;
+           for (var i in data){
+               var html = '<div style="margin-top: 10px;"><a href="'+data[i].img_url+'" target="_blank"><img src="'+ data[i].img_url +'" class="layui-upload-img" style="margin-left: 5px;min-width: 80px; height: 100px;max-width: 200px;"></a>' +
+                      '<div align="center" style="margin-top: 3px;"><button type="button" class="layui-btn layui-btn-danger layui-btn-xs" onclick="delImage('+data[i].id+')">删除</button></div></div>';
+                $('#show_image_'+ data[i].type).append(html)
+           }
+        }
+    });
+  }
+
+  function delImage(id) {
+      layui.admin.req({
+         url: '/vehicle/model_images/'+id + '/'
+         ,type: 'delete'
+         ,done: function(res){
+             refresh();
+         }
+      });
+  }
+
+  </script>
+</body>
+</html>

+ 105 - 0
uis/views/vehicle_model/upload_poster.html

@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>添加员工信息</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+  <link rel="stylesheet" type="text/css" href="../../layuiadmin/style/formSelects-v4.css"/>
+    <style>
+        img{
+            width: 40%;
+            height: 30%;
+        }
+    </style>
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+      <div class="layui-col-md6">
+        <div class="layui-card">
+
+          <div class="layui-card-body">
+            <form class="layui-form" action="" lay-filter="component-form-element">
+              <div class="layui-row layui-col-space10 layui-form-item">
+               <div class="layui-col-lg6">
+                  <label class="layui-form-label">海报图片:</label>
+                  <div class="layui-input-block">
+                      <button type="button" class="layui-btn-sm" id="upload_image">上传图片</button><br><br>
+                      <img class="layui-upload-img" id="show_image">
+                  </div>
+               </div>
+                <button class="layui-btn" id="id_save" lay-submit lay-filter="component-form-element" style="display: none">保存</button>
+                  <button class="layui-btn" type="button" id="upload_save" style="display: none"></button>
+              </div>
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+
+  <script src="../../layuiadmin/layui/layui.js"></script>
+  <script>
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index',
+    formSelects: 'formSelects-v4'
+  }).use(['index', 'form', 'utils', 'upload'], function(){
+    var $ = layui.$
+    ,admin = layui.admin
+    ,upload = layui.upload
+    ,form = layui.form;
+    var id = layui.view.getParameterByName('id');
+    var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
+    if(editdata.playbill_url){
+        $('#show_image').attr('src', editdata.playbill_url);
+    }
+
+    form.render(null, 'component-form-element');
+
+    var form_data = {field:{}};
+    upload.render({
+         elem: '#upload_image',
+         url: '/vehicle/model/' +id + '/upload_playbill/',
+         auto: false,
+         field: 'image',
+         bindAction: '#upload_save',
+         choose: function(obj) {
+             obj.preview(
+                 function(index, file, result) {
+                     $('#show_image').attr('src', result);
+                 }
+             );
+         },
+        done: function (res) {
+            if (res.code != 0) {
+                layer.msg(res.msg);
+            }else {
+                parent.layui.onSubmitChild(res.data);
+            }
+        },
+        error: function () {
+            layer.msg('上传失败');
+        }
+    });
+
+    form.on('submit(component-form-element)', function (data) {
+         form_data = data;
+         $('#upload_save').click();
+        return false;
+    });
+
+    parent.layui.submitChild = function () {
+      $("#id_save").click();
+    };
+  });
+  </script>
+</body>
+</html>

+ 104 - 0
uis/views/vehicle_series/brand_edit.html

@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>添加员工信息</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+  <link rel="stylesheet" type="text/css" href="../../layuiadmin/style/formSelects-v4.css"/>
+     <style>
+        img{
+            width: 40%;
+            height: 30%;
+        }
+    </style>
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+      <div class="layui-col-md6">
+        <div class="layui-card">
+
+          <div class="layui-card-body">
+            <form class="layui-form" action="" lay-filter="component-form-element">
+              <div class="layui-row layui-col-space10 layui-form-item">
+
+                <div class="layui-col-lg6">
+                  <label class="layui-form-label"><font color='red' size="4">*</font>名称:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="name" lay-verify="required" placeholder="请输入名称" autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                <div class="layui-col-lg6">
+                  <label class="layui-form-label">是否在用:</label>
+                  <div class="layui-input-block">
+                    <input type="checkbox" name="enabled" lay-skin="switch" lay-text="是|否" checked="" value="1">
+                  </div>
+                </div>
+                 <div class="layui-col-lg6">
+                  <label class="layui-form-label">备注:</label>
+                  <div class="layui-input-block">
+                    <input type="text" name="notes" placeholder="请输入备注"  autocomplete="off" class="layui-input">
+                  </div>
+                </div>
+                <button id="id_save" class="layui-btn" lay-submit lay-filter="component-form-element" style="display: none">保存</button>
+              </div>
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+
+  <script src="../../layuiadmin/layui/layui.js"></script>
+  <script>
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index',
+    formSelects: 'formSelects-v4'
+  }).use(['index', 'form', 'utils'], function(){
+    var $ = layui.$
+    ,admin = layui.admin
+    ,upload = layui.upload
+    ,form = layui.form;
+    var id = layui.view.getParameterByName('id');
+
+    if(id){
+        var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
+        form.val("component-form-element", editdata);
+    }
+    form.on('submit(component-form-element)', function(data){
+
+      //layer.msg(JSON.stringify(data.field));
+        if (id){
+            var url =  '/vehicle/brand/' + id + '/';
+            var type = 'put';
+        }else{
+            url =  '/vehicle/brand/';
+            type = 'post'
+        }
+         admin.req({
+        url: url
+        ,data: data.field
+        ,type: type
+        ,done: function(res){
+            parent.layui.onSubmitChild(res.data);
+        }
+      });
+
+      return false;
+    });
+
+    parent.layui.submitChild = function () {
+      $("#id_save").click();
+    };
+  });
+  </script>
+</body>
+</html>

+ 263 - 0
uis/views/vehicle_series/index.html

@@ -0,0 +1,263 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>车辆设置</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+    <style type="text/css">
+        .seach_items {float:right;margin-left: 10px;}
+    </style>
+
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body" pad15>
+        <div class="layui-row layui-col-space15">
+          <div class="layui-col-md5">
+            <div class="LAY-btns" style="margin-bottom: 10px;">
+                <div class="layui-col-xs2">
+                    <button class="layui-btn" id="brand_add"><i class="layui-icon layui-icon-add-circle"></i>添加</button>
+                </div>
+                    <form class="layui-form" lay-filter="query-form-element1">
+                        <div class="seach_items">
+                            <button class="layui-btn" lay-submit lay-filter="query-form-element1"><i class="layui-icon layui-icon-search"></i>查询</button>
+                        </div>
+                        <div class="seach_items">
+                            <input type="text"  name="name" autocomplete="off" class="layui-input" placeholder="名称"/>
+                        </div>
+                    </form>
+                <div style="clear: both;"></div>
+            </div>
+            <table class="layui-hide" id="brand_datagrid" lay-filter="brand-operate"></table>
+
+            <script type="text/html" id="brand-operate-bar">
+                <div class="layui-btn-group">
+              <a class="layui-btn layui-btn-xs" lay-event="brand_edit" >修改</a>
+              <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="brand_del">删除</a>
+                </div>
+            </script>
+          </div>
+
+          <div class="layui-col-md7">
+            <div class="LAY-btns" style="margin-bottom: 10px;">
+              <div class="layui-col-xs2">
+                    <button class="layui-btn" id="series_add"><i class="layui-icon layui-icon-add-circle"></i>添加</button>
+                </div>
+
+                    <form class="layui-form" lay-filter="query-form-element2">
+                        <div class="seach_items">
+                            <button class="layui-btn" lay-submit lay-filter="query-form-element2"><i class="layui-icon layui-icon-search"></i>查询</button>
+                        </div>
+                        <div class="seach_items">
+                            <input type="text"  name="name" autocomplete="off" class="layui-input" placeholder="车系名称"/>
+                        </div>
+                        <div class="seach_items">
+                            <input type="text"  name="brand_name" autocomplete="off" class="layui-input" placeholder="品牌名称"/>
+                        </div>
+                    </form>
+                <div style="clear: both;"></div>
+                </div>
+
+            <table class="layui-hide" id="series_datagrid" lay-filter="series-operate"></table>
+
+            <script type="text/html" id="series-operate-bar">
+                <div class="layui-btn-group">
+              <a class="layui-btn layui-btn-xs" lay-event="series_edit" >修改</a>
+              <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="series_del">删除</a>
+                </div>
+            </script>
+          </div>
+        </div>
+        </div>
+    </div>
+  </div>
+  <script src="../../layuiadmin/layui/layui.js?t=1"></script>
+  <script>
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index' //主入口模块
+  }).use(['index', 'table', 'form'], function(){
+    var $ = layui.$;
+    var table = layui.table
+        ,form = layui.form
+        ,admin = layui.admin;
+      //品牌
+    table.render({
+      elem: '#brand_datagrid'
+      ,url: '/vehicle/brand/'
+      ,cols: [[
+        {field:'name', title:'名称', width:150}
+        ,{field:'enabled_text', title:'在用', width: 80}
+        ,{field:'notes', title:'备注', minWidth: 80}
+        ,{width:110, align:'center', fixed: 'right', toolbar: '#brand-operate-bar'}
+      ]]
+      ,page: true
+      ,height: 'full-108'
+      , done: function () {
+        layui.index.removeNoPermButtons()
+      }
+    });
+    //车系
+    table.render({
+      elem: '#series_datagrid'
+      ,url: '/vehicle/series/'
+      ,cols: [[
+        {field:'brand_name', title:'品牌名称', width:100}
+        ,{field:'name', title:'车系名称', width:200}
+        ,{field:'min_price', title:'最低指导价', width:100}
+        ,{field:'is_hot_text', title:'是否热门', width: 100}
+        ,{field:'enabled_text', title:'在用', width: 80}
+        ,{field:'notes', title:'备注'}
+        ,{width:110, align:'center', fixed: 'right', toolbar: '#series-operate-bar'}
+      ]]
+      ,page: true
+      ,height: 'full-145'
+      , done: function () {
+        layui.index.removeNoPermButtons()
+      }
+    });
+
+    //监听品牌工具条
+    table.on('tool(brand-operate)', function(obj) {
+        var data = obj.data;
+        if (obj.event === 'brand_del') {
+            layer.confirm('确定要删除吗?', function (index) {
+                layer.close(index);
+                layui.admin.req({
+                    url: '/vehicle/brand/' + data.id + '/'
+                    ,type: 'delete'
+                    , done: function (res) {
+                        table.reload('brand_datagrid', {});
+                        //obj.del();
+                    }
+                });
+            });
+        } else if (obj.event === 'brand_edit') {
+            table.editdata = data;
+            layer.open({
+                type: 2,
+                title: '修改',
+                shadeClose: false,
+                area: ['450px', '350px'],
+                btn:['保存','取消'],
+                yes: function (index, dom) {
+                    layui.onSubmitChild = function (data) {
+                        layer.close(index);
+                        table.reload('brand_datagrid', {});
+                        table.reload('series_datagrid', {});
+                      };
+                      layui.submitChild();
+                  },
+                  btn2: function(index, layero){
+                    layer.close(index);//关闭当前按钮
+                  },
+                content: 'brand_edit.html?id=' + data.id
+            });
+        }
+    });
+    //监听车系工具条
+    table.on('tool(series-operate)', function(obj){
+      var data = obj.data;
+        if(obj.event === 'series_del'){
+        layer.confirm('确定要删除吗?', function(index){
+          layui.admin.req({
+            url: '/vehicle/series/'+data.id + '/'
+            ,type: 'delete'
+            ,done: function(res){
+              table.reload('series_datagrid',{});
+              layer.close(index);
+            }
+          });
+        });
+      } else if(obj.event === 'series_edit'){
+        table.editdata = data;
+        layer.open({
+          type: 2,
+          title: '修改',
+         area: ['40%', '60%'],
+          btn:['保存','取消'],
+          yes: function (index, dom) {
+            layui.onSubmitChild = function (data) {
+                layer.close(index);
+                table.reload('brand_datagrid', {});
+                table.reload('series_datagrid', {});
+              };
+              layui.submitChild();
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'series_edit.html?id='+data.id
+        });
+      }
+    });
+    form.on('submit(query-form-element1)', function(data){
+      table.reload('brand_datagrid', {
+          where: data.field
+          ,page:{curr:1}
+      });
+      layer.closeAll();
+      return false
+    });
+    form.on('submit(query-form-element2)', function(data){
+      table.reload('series_datagrid', {
+          where: data.field
+          ,page:{curr:1}
+      });
+      layer.closeAll();
+      return false
+    });
+    $('#brand_add').on('click', function(){
+        layer.open({
+          type: 2,
+          title: '添加',
+          area: ['450px', '350px'],
+          btn:['保存','取消'],
+          yes: function (index, dom) {
+            layui.onSubmitChild = function (data) {
+                layer.close(index);
+                table.reload('brand_datagrid', {});
+                table.reload('series_datagrid', {});
+              };
+              layui.submitChild();
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'brand_edit.html'
+        });
+    });
+    $('#series_add').on('click', function(){
+        layer.open({
+          type: 2,
+          title: '添加',
+          area: ['40%', '70%'],
+          btn:['保存','取消'],
+          yes: function (index, dom) {
+            layui.onSubmitChild = function (data) {
+                layer.close(index);
+                table.reload('brand_datagrid', {});
+                table.reload('series_datagrid', {});
+              };
+              layui.submitChild();
+          },
+          btn2: function(index, layero){
+            layer.close(index);//关闭当前按钮
+          },
+          content: 'series_edit.html'
+        });
+    });
+});
+
+
+
+  </script>
+</body>
+</html>

+ 205 - 0
uis/views/vehicle_series/series_edit.html

@@ -0,0 +1,205 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>添加员工信息</title>
+    <meta name="renderer" content="webkit">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport"
+          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+    <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+    <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
+    <link rel="stylesheet" type="text/css" href="../../layuiadmin/style/formSelects-v4.css"/>
+    <style>
+        img {
+            width: 40%;
+            height: 30%;
+        }
+    </style>
+</head>
+<body>
+
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-card">
+
+            <div class="layui-card-body" pad15>
+                <form class="layui-form" action="" lay-filter="component-form-element">
+                    <div class="layui-row layui-col-space10 layui-form-item">
+                        <div>
+                            <label class="layui-form-label"><font color='red' size="4">*</font>品牌:</label>
+                            <div class="layui-input-block">
+                                <select id="id_brand" name="brand" lay-verify="required">
+                                </select>
+                            </div>
+                        </div>
+                        <div>
+                            <label class="layui-form-label"><font color='red' size="4">*</font>名称:</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="name" lay-verify="required" placeholder="请输入名称"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-col-lg6">
+                            <label class="layui-form-label">热门:</label>
+                            <div class="layui-input-block">
+                                <input type="checkbox" name="is_hot" lay-skin="switch" lay-text="是|否" checked=""
+                                       value="1">
+                            </div>
+                        </div>
+                        <div>
+                            <label class="layui-form-label">在用:</label>
+                            <div class="layui-input-block">
+                                <input type="checkbox" name="enabled" lay-skin="switch" lay-text="是|否" checked=""
+                                       value="1">
+                            </div>
+                        </div>
+                        <div>
+                            <label class="layui-form-label">备注:</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="notes" placeholder="请输入备注" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div>
+                            <label class="layui-form-label">最低价:</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="min_price" placeholder="请输入" lay-verify="numberGez"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div>
+                            <label class="layui-form-label">车系展示:</label>
+                            <div class="layui-input-block">
+                                <button type="button" class="layui-btn-sm" id="test1">上传图片</button>
+                                <br><br>
+                                <img class="layui-upload-img" id="demo1">
+                            </div>
+                        </div>
+                        <button id="id_save" class="layui-btn" lay-submit lay-filter="component-form-element"
+                                style="display: none">保存
+                        </button>
+                        <button class="layui-btn" type="button" id="upload_image" style="display: none"></button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+
+
+<script src="../../layuiadmin/layui/layui.js"></script>
+<script>
+    layui.config({
+        base: '../../../layuiadmin/' //静态资源所在路径
+    }).extend({
+        index: 'lib/index',
+        formSelects: 'formSelects-v4'
+    }).use(['index', 'form', 'utils', 'upload'], function () {
+        var $ = layui.$
+            , admin = layui.admin
+            , upload = layui.upload
+            , form = layui.form;
+        var id = layui.view.getParameterByName('id');
+
+        admin.req({
+            url: '/vehicle/dict/',
+            done: function (res) {
+                var brand = res.data.brand;
+                var brand_node = $('#id_brand');
+                for (var i in brand) {
+                    var pid = brand[i].id;
+                    var value = brand[i].name;
+                    brand_node.append("<option value='" + pid + "'>" + value + "</option>");
+                }
+                form.render();
+                loadData();
+            }
+        });
+        var loadData = function () {
+            if (id) {
+                var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
+                form.val("component-form-element", editdata);
+                if (editdata.img_url) {
+                    $('#demo1').attr('src', editdata.img_url);
+                }
+            }
+        };
+        form.render(null, 'component-form-element');
+
+        var form_data = {field: {}};
+
+        if (id) {
+            var url = '/vehicle/series/' + id + '/update_series/';
+        } else {
+            url = '/vehicle/series/';
+        }
+        upload.render({
+            elem: '#test1',
+            url: url,
+            auto: false,
+            field: 'image',
+            bindAction: '#upload_image',
+            choose: function (obj) {
+                obj.preview(
+                    function (index, file, result) {
+                        $('#demo1').attr('src', result);
+                    }
+                );
+            },
+            data: {
+                brand: function () {
+                    return form_data.field.brand;
+                },
+                name: function () {
+                    return form_data.field.name;
+                },
+                notes: function () {
+                    return form_data.field.notes;
+                },
+                enabled: function () {
+                    if (form_data.field.enabled) {
+                        return form_data.field.enabled;
+                    } else {
+                        return '0'
+                    }
+                }
+            },
+            done: function (res) {
+                if (res.code != 0) {
+                    layer.msg(res.msg);
+                } else {
+                    parent.layui.onSubmitChild(res.data);
+                }
+            },
+            error: function () {
+                layer.msg('保存失败');
+            }
+        });
+
+        form.on('submit(component-form-element)', function (data) {
+            //layer.msg(JSON.stringify(data.field));
+            if (data.field.image) {
+                form_data = data;
+                $('#upload_image').click();
+            } else {
+                admin.req({
+                    url: url
+                    , data: data.field
+                    , type: 'post'
+                    , done: function (res) {
+                        parent.layui.onSubmitChild(res.data);
+                    }
+                });
+            }
+
+            return false;
+        });
+
+        parent.layui.submitChild = function () {
+            $("#id_save").click();
+        };
+    });
+</script>
+</body>
+</html>

+ 58 - 0
utils/permission.py

@@ -0,0 +1,58 @@
+# coding=utf-8
+
+from rest_framework import permissions
+
+from utils.exceptions import CustomError
+
+class isLogin(permissions.BasePermission):
+    def has_permission(self, request, view):
+        if not request.user or not request.user.is_authenticated:
+            return False
+        return True
+
+def check_permission(request, perm):
+    if not request.user or not request.user.is_authenticated:
+        raise CustomError(u"身份认证失败,请重新登录!")
+    from django.contrib.auth.models import Permission
+    ps = perm.split('.')
+    if request.user.has_perm(perm):
+        return True
+    else:
+        try:
+            p = Permission.objects.get(codename=ps[1], content_type__app_label=ps[0])
+        except:
+            raise CustomError(u"权限配置错误!")
+        raise CustomError(u"您没有[%s--%s]权限,无法执行该操作,请联系管理员分配权限!" % (p.content_type.name, p.name))
+
+decorator_with_arguments = lambda decorator: lambda *args, **kwargs: lambda func: decorator(func, *args, **kwargs)
+
+@decorator_with_arguments
+def permission_required(function, perm):
+    def _function(viewset, *args, **kwargs):
+        # user_id = viewset.request.META.get('HTTP_USER_ID')
+        # token = viewset.request.META.get('HTTP_Authorization')
+        # if user_id and token:
+        #     try:
+        #         user = User.objects.get(pk=user_id)
+        #     except:
+        #         return ForbiddenJSONResponse()
+
+            # valid = token_generator.check_token(user, token)
+            # if valid:
+            #     request.user = user
+            # viewset.request.user = user
+        # else:
+        #     return ForbiddenJSONResponse()
+
+        if viewset.request.user.has_perm(perm):
+            return function(viewset, *args, **kwargs)
+        else:
+            from django.contrib.auth.models import Permission
+            ps = perm.split('.')
+            try:
+                p = Permission.objects.get(codename=ps[1], content_type__app_label=ps[0])
+            except:
+                raise CustomError(u"权限配置错误!")
+
+            raise CustomError(u"您没有[%s-%s]权限,无法执行该操作,请联系管理员分配权限!" % (p.content_type.name, p.name))
+    return _function