Procházet zdrojové kódy

用户、自定义项

lyh před 1 rokem
rodič
revize
b049b3d4dc

+ 14 - 0
apps/account/filters.py

@@ -0,0 +1,14 @@
+# coding=utf-8
+
+import django_filters
+
+from .models import User
+
+class EmployeeFilter(django_filters.FilterSet):
+    status = django_filters.CharFilter(field_name='status')
+    username = django_filters.CharFilter(field_name='username', lookup_expr='icontains')
+    name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
+
+    class Meta:
+        model = User
+        fields = '__all__'

+ 9 - 2
apps/account/models.py

@@ -105,12 +105,19 @@ class User(AbstractBaseUser, PermissionsMixin):
 
 
     def __str__(self):
-        return self.name
+        return self.username
 
     def __unicode__(self):
-        return self.name
+        return self.username
+
     class Meta:
         db_table = "auth_user"
         verbose_name = u"人员管理"
         ordering = ('-id',)
         default_permissions = ()
+        permissions = [
+            ('browse_group', u'查看'),
+            ('add_group', u'添加'),
+            ('edit_group', u'修改'),
+            ('delete_group', u'删除'),
+        ]

+ 26 - 2
apps/account/serializers.py

@@ -1,5 +1,5 @@
 # coding=utf-8
-
+import json
 from django.contrib.auth import get_user_model, authenticate
 
 from rest_framework import serializers
@@ -8,6 +8,7 @@ from rest_framework_jwt.settings import api_settings
 from apps.foundation.models import BizLog
 from apps.account import tenant_log
 from utils import get_remote_addr
+from utils.exceptions import CustomError
 
 User = get_user_model()
 jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
@@ -46,4 +47,27 @@ class TenantJWTSerializer(JSONWebTokenSerializer):
         else:
             msg = u'必须包含“{username field}”和“password.'
             msg = msg.format(username_field=self.username_field)
-            raise serializers.ValidationError(msg)
+            raise serializers.ValidationError(msg)
+
+class EmployeeSerializer(serializers.ModelSerializer):
+
+    create_time = serializers.DateTimeField(source='date_joined', read_only=True)
+    status_text = serializers.SerializerMethodField()
+
+    def get_status_text(self, obj):
+        return User.STATUS_CHOICES[obj.status][1]
+
+    class Meta:
+        model = User
+        fields = '__all__'
+
+    def create(self, validated_data):
+        instance = super(EmployeeSerializer, self).create(validated_data)
+        return instance
+
+    def update(self, instance, validated_data):
+        if 'user' in validated_data:
+            instance.user.update_item(validated_data['user'])
+            validated_data.pop('user')
+        instance = super(EmployeeSerializer, self).update(instance, validated_data)
+        return instance

+ 5 - 1
apps/account/urls.py

@@ -9,4 +9,8 @@ urlpatterns = [
      url(r'^login/$', LoginView.as_view()),
      url(r'^token_refresh/$', RefreshTokenView.as_view()),
      url(r'^token_verify/$', VerifyTokenView.as_view()),
-]
+]
+
+router = SimpleRouter()
+router.register(r'employee', EmployeeViewSet)
+urlpatterns += router.urls

+ 38 - 4
apps/account/views.py

@@ -1,10 +1,15 @@
 # coding=utf-8
-
+from django.db import transaction
 from rest_framework_jwt.views import ObtainJSONWebToken,VerifyJSONWebToken,RefreshJSONWebToken
 from rest_framework.serializers import ValidationError
-
+from utils.custom_modelviewset import CustomModelViewSet
 from utils import response_error, response_ok
-from .serializers import TenantJWTSerializer
+from .serializers import *
+from .models import User
+from apps.account import tenant_log
+from apps.foundation.models import BizLog
+from django.contrib.auth.decorators import login_required
+from .filters import *
 
 class LoginView(ObtainJSONWebToken):
     serializer_class = TenantJWTSerializer
@@ -36,4 +41,33 @@ class RefreshTokenView(RefreshJSONWebToken):
             if ser.is_valid(raise_exception=True):
                 return response_ok({'token': ser.validated_data['token']})
         except ValidationError as e:
-            return response_error(u'登录状态失效,请重新登录[' + e.detail['error'][0] + ']')
+            return response_error(u'登录状态失效,请重新登录[' + e.detail['error'][0] + ']')
+
+class EmployeeViewSet(CustomModelViewSet):
+    queryset = User.objects.filter()
+    serializer_class = EmployeeSerializer
+
+    def filter_queryset(self, queryset):
+        queryset = queryset.filter()
+        f = EmployeeFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def perform_create(self, serializer):
+        super(EmployeeViewSet, 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(EmployeeViewSet, 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.user.is_active = False
+            instance.user.save()
+            tenant_log(self.request.user, BizLog.DELETE, u'禁用用户[%s],id=%d' % (instance.name, instance.id))
+        return response_ok()

+ 14 - 0
apps/foundation/filters.py

@@ -0,0 +1,14 @@
+# coding=utf-8
+
+import django_filters
+
+from .models import Option
+
+
+class OptionFilter(django_filters.FilterSet):
+    name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
+    type = django_filters.CharFilter(field_name='type')
+
+    class Meta:
+        model = Option
+        fields = '__all__'

+ 5 - 12
apps/foundation/models.py

@@ -10,25 +10,18 @@ from utils.exceptions import CustomError
 from utils.format import strftime, strfdate
 
 class Option(models.Model):
-    PAYMENT_MODE = 0
-    MATERIAL_MODE = 1
-    CONSUMABLE_MODE = 2
-    GOODS_MODE = 3
-    QUALITY_REQUEST = 4
+    USED_VEHICLE_BRAND = 0
+    MAINT_TYPE = 1
 
     TYPE_CHOICES = (
-        (PAYMENT_MODE, u'付款方式'),
-        (MATERIAL_MODE, u'原料类别'),
-        (CONSUMABLE_MODE, u'耗材类别'),
-        (GOODS_MODE, u'成品类别'),
-        (QUALITY_REQUEST, u'质量要求'),
+        (USED_VEHICLE_BRAND, u'二手车品牌'),
+        (MAINT_TYPE, u'服务类型'),
     )
 
     type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"类别")
     name = models.CharField(max_length=100, verbose_name=u"名称")
     notes = models.CharField(max_length=500, verbose_name=u"备注",blank=True,null=True)
-    enabled = models.BooleanField(verbose_name=u"在用", default=True)
-
+    enable = models.BooleanField(verbose_name=u"在用", default=True)
 
     @staticmethod
     def getTypeText(type):

+ 26 - 0
apps/foundation/serializers.py

@@ -0,0 +1,26 @@
+# coding=utf-8
+
+from rest_framework import serializers
+from .models import Option
+
+
+class OptionSerializer(serializers.ModelSerializer):
+    type_name = serializers.CharField(source='get_type_display', read_only=True)
+    enable_text = serializers.SerializerMethodField()
+
+    def get_enable_text(self, obj):
+        if obj.enable:
+            return u'是'
+        return u'否'
+
+    class Meta:
+        model = Option
+        fields = '__all__'
+
+    def create(self, validated_data):
+        instance = super(OptionSerializer, self).create(validated_data)
+        return instance
+
+    def update(self, instance, validated_data):
+        instance = super(OptionSerializer, self).update(instance, validated_data)
+        return instance

+ 15 - 0
apps/foundation/urls.py

@@ -0,0 +1,15 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'option/dict/$', OptionDictView.as_view()),
+    url(r'search/$', OptionSearchSearch.as_view()),
+]
+
+router = SimpleRouter()
+router.register(r'option', OptionViewSet)
+urlpatterns += router.urls

+ 87 - 0
apps/foundation/views.py

@@ -0,0 +1,87 @@
+# coding=utf-8
+
+from django.db import transaction
+from rest_framework.views import APIView
+from rest_framework.decorators import action
+from utils import response_ok
+from utils.custom_modelviewset import CustomModelViewSet
+from utils.exceptions import CustomError
+from apps.foundation.models import BizLog, Option
+from apps.account import tenant_log
+from .filters import OptionFilter
+from .serializers import OptionSerializer
+
+class OptionDictView(APIView):
+
+    def get(self, request):
+        ret = {
+            'types':Option.TYPE_CHOICES,
+        }
+        return response_ok(ret)
+
+class OptionViewSet(CustomModelViewSet):
+    queryset = Option.objects.filter()
+    serializer_class = OptionSerializer
+
+    def filter_queryset(self, queryset):
+        queryset = queryset.filter()
+        f = OptionFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def perform_create(self, serializer):
+        super(OptionViewSet, 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(OptionViewSet, 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()
+
+    def create_default(self, request):
+        if not self.request.user.has_perm('option.add_option'):
+            raise CustomError(u"您没有[系统选项-添加]权限,无法执行该操作,请联系管理员分配权限!")
+        tenant = request.user.employee.tenant
+        with transaction.atomic():
+            for default in Option.DEFAULT_OPTION:
+                default['tenant'] = tenant
+                is_exist = Option.is_exist(tenant, default['type'], default['name'])
+                if is_exist:
+                    continue
+                Option.objects.create(**default)
+            tenant_log(self.request.user, BizLog.INSERT, u'添加默认系统选项')
+        return response_ok()
+
+
+class OptionSearchSearch(APIView):
+    def get(self, request):
+        type = request.GET.get('type')
+        keyword = request.GET.get('keyword')
+        rows = Option.objects.filter(delete=False, enable=True, tenant=request.user.employee.tenant)
+        if type:
+            rows = rows.filter(type=int(type))
+
+        if keyword:
+            rows = rows.filter(name__icontains=keyword)
+
+        data = []
+        for row in rows:
+            item ={
+                'value': row.id,
+                'id': row.id,
+                'name': row.name,
+                'notes': row.notes
+            }
+            data.append(item)
+
+        return response_ok(data)

+ 1 - 0
shop/urls.py

@@ -24,6 +24,7 @@ from apps.dashboard.views import index
 urlpatterns = [
     url(r'^$', index),
     url(r'^account/', include('apps.account.urls')),
+    url(r'^foundation/', include('apps.foundation.urls')),
     # url(r'^tenant/', include('apps.tenant.urls')),
     # url(r'^customer/', include('apps.customer.urls')),
     # url(r'^api/', include('apps.api.urls')),

+ 6 - 31
uis/views/account/employee.html

@@ -18,7 +18,7 @@
           <div class="layui-col-md12">
 
             <div class="LAY-btns" style="margin-bottom: 10px;">
-              <button class="layui-btn layui-btn-sm" data-permission="account.add_user" id="btn_add"><i class="layui-icon layui-icon-add-circle"></i>添加</button>
+              <button class="layui-btn layui-btn-sm" id="btn_add"><i class="layui-icon layui-icon-add-circle"></i>添加</button>
               <button class="layui-btn layui-btn-sm" id="btn_query"><i class="layui-icon layui-icon-search"></i>查询</button>
             </div>
 
@@ -26,9 +26,8 @@
 
             <script type="text/html" id="datagrid-operate-bar">
                 <div class="layui-btn-group">
-                  <a class="layui-btn layui-btn-xs" data-permission="account.add_user" lay-event="edit">修改</a>
-                  <a class="layui-btn layui-btn-danger layui-btn-xs" data-permission="account.delete_user" lay-event="delete">删除</a>
-                  <a class="layui-btn layui-btn-xs layui-btn-warm" data-permission="account.add_user" lay-event="manage_range">管理范围</a>
+                  <a class="layui-btn layui-btn-xs" lay-event="edit">修改</a>
+                  <a class="layui-btn layui-btn-danger layui-btn-xs"  lay-event="delete">删除</a>
                 </div>
             </script>
           </div>
@@ -76,19 +75,15 @@
 
     table.render({
       elem: '#datagrid'
-      ,url: '/account/employee/data/'
+      ,url: '/account/employee/'
       ,cols: [[
         {field:'name', title:'姓名', width:100}
         ,{field:'username', title:'登录账号',width: 100}
-        ,{field:'groups', title:'权限组', width:200}
-        ,{field:'gender_text', title:'性别', width:80}
         ,{field:'tel', title:'手机号码',width: 130}
-        ,{field:'department_text', title:'所属部门', width:150}
-        ,{field:'ID_card', title:'身份证号码',width: 180}
         ,{field:'address', title:'家庭住址',minWidth: 200}
         ,{field:'status_text', title:'是否在职', width:90}
         ,{field:'title', title:'工作岗位', width:100}
-        ,{width:170, align:'left', fixed: 'right', toolbar: '#datagrid-operate-bar'}
+        ,{width:100, align:'left', fixed: 'right', toolbar: '#datagrid-operate-bar'}
       ]]
       ,page: true
       ,height: 'full-104'
@@ -120,27 +115,7 @@
           },
           content: 'employee_edit.html?id='+data.id
         });
-      } else if(obj.event === 'manage_range'){
-         table.editdata = data;
-         layer.open({
-          type: 2,
-          title: '管理范围',
-          shadeClose: false,
-          area: ['650px', '80%'],
-          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: 'manage_range.html?id='+data.id
-        });
-      }else if(obj.event === 'delete'){
+      } else if(obj.event === 'delete'){
          layer.confirm('确定要删除吗?', function(index){
              layer.close(index);
             layui.admin.req({

+ 15 - 66
uis/views/account/employee_edit.html

@@ -63,28 +63,6 @@
                   </div>
                 </div>
 
-                <div class="layui-col-lg6">
-                    <label class="layui-form-label"><font color='red' size="4">*</font>所属部门:</label>
-                    <div class="layui-input-block" id="department_selecter">
-                      <select name="department" xm-select="selectDepartment" xm-select-radio lay-verify="required">
-                      </select>
-                    </div>
-                  </div>
-
-                <div class="layui-col-lg6">
-                  <label class="layui-form-label">权限组:</label>
-                  <div class="layui-input-block" id="group_selecter">
-                    <select name="groups" xm-select="selectGroup"></select>
-                  </div>
-                </div>
-
-                <div class="layui-col-lg6">
-                  <label class="layui-form-label">身份证号:</label>
-                  <div class="layui-input-block">
-                    <input type="text" name="ID_card" placeholder="" autocomplete="off" class="layui-input">
-                  </div>
-                </div>
-
                 <div class="layui-col-lg6">
                   <label class="layui-form-label">家庭住址:</label>
                   <div class="layui-input-block">
@@ -133,11 +111,9 @@
     ,dep_formSelects = layui.formSelects;
 
     var editdata = null;
-    var department = '';
     var id = layui.view.getParameterByName('id');
 
     if(id){
-      department = parent.layui.table.editdata.department;
       editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
       editdata.password = '';
       if (editdata.status == 1) {
@@ -152,53 +128,26 @@
         form.val("component-form-element", editdata);
     }
 
-    dep_formSelects.value('selectDepartment', []);
-    admin.req({
-        url: '/account/department/tree/'
-        ,done: function(res){
-            dep_formSelects.data('selectDepartment', 'local', {
-            arr: res.data,
-            tree: {
-                //在点击节点的时候, 如果没有子级数据, 会触发此事件
-                nextClick: function(id, item, callback){
-                    return false;
-                    },
-                }
-            });
-            dep_formSelects.value('selectDepartment', [department]);
-        }
-    });
-
-    formSelects.config('selectGroup', {
-      beforeSuccess:function(eid, url, searchVal, result){
-          if(id){
-              var groupIds = parent.layui.table.editdata.group_ids;
-              for(var n in result.data){
-                  var item = result.data[n];
-                  if(groupIds.indexOf(parseInt(item.value)) > -1)
-                      item.selected = 'selected';
-              }
-          }
-
-          return result;
-      }
-    });
-    formSelects.data('selectGroup', 'server', {
-        url: '/account/group/combobox/data/'
-    });
-
     form.on('submit(component-form-element)', function(data){
-      var submitData = data.field;
-      submitData.groups = formSelects.value('selectGroup', 'val');
+      if (!data.field['status']){
+          data.field['status'] = 0;
+      }
+      if (id){
+          var url = '/account/employee/'+id + '/';
+          var type = 'put';
+      }else{
+          url =  '/account/employee/';
+          type = 'post';
+      }
       admin.req({
-        url: '/account/employee/save/?id='+id
-        ,data: JSON.stringify(submitData)
-        ,type: 'post'
+        url: url
+        ,data: data.field
+        ,type: type
         ,done: function(res){
-            parent.layui.onSubmitChild(res.data);
+            parent.layer.closeAll('iframe');
+            parent.layui.table.reload('datagrid',{});
         }
       });
-
       return false;
     });
     parent.layui.submitChild = function () {

+ 1 - 1
uis/views/account/login.html

@@ -70,7 +70,7 @@
 
     if (layui.data(setter.tableName)[setter.request.tokenName]) {
       admin.req({
-        url: '/tenant/token_refresh/'
+        url: '/account/token_refresh/'
         ,data: {token: layui.data(setter.tableName)[setter.request.tokenName].substr(4)}
         ,type: 'post'
         ,done: function(res){

+ 18 - 182
uis/views/index.html

@@ -67,7 +67,7 @@
                 <cite>公告管理</cite>
               </a>
               <dl class="layui-nav-child">
-                <dd data-name="button" data-permission="office.view_notice">
+                <dd data-name="button">
                   <a lay-href="notice/notice.html">公告管理</a>
                 </dd>
               </dl>
@@ -78,13 +78,13 @@
                 <cite>销售管理</cite>
               </a>
               <dl class="layui-nav-child">
-                <dd data-name="button" data-permission="plan.view_sale_plan">
+                <dd data-name="button">
                   <a lay-href="plan/sale.html">销售计划管理</a>
                 </dd>
-                <dd data-name="button" data-permission="order.view_sale_order">
+                <dd data-name="button">
                   <a lay-href="order/sale_order.html">销售订单管理</a>
                 </dd>
-                <dd data-name="button" data-permission="product.view_goods_product">
+                <dd data-name="button" >
                   <a lay-href="goods/goods_stock_query.html">成品库存查询</a>
                 </dd>
               </dl>
@@ -95,7 +95,7 @@
                 <cite>生产管理</cite>
               </a>
               <dl class="layui-nav-child">
-                <dd data-name="nav" data-permission="plan.view_production_plan">
+                <dd data-name="nav" >
                   <a lay-href="plan/production.html">生产计划管理</a>
                 </dd>
               </dl>
@@ -106,198 +106,48 @@
                 <cite>采购管理</cite>
               </a>
               <dl class="layui-nav-child">
-                <dd data-name="button" data-permission="purchase.view_purchase_plan">
+                <dd data-name="button">
                   <a lay-href="purchase/purchase.html">计划管理</a>
                 </dd>
-                <dd data-name="button" data-permission="purchase.view_purchase_user_plan">
+                <dd data-name="button">
                   <a lay-href="purchase/purchase_price.html">询价管理</a>
                 </dd>
-                <dd data-name="button" data-permission="purchase.view_purchase_order">
+                <dd data-name="button">
                     <a lay-href="purchase/purchase_order.html">合同管理</a>
                   </dd>
-                <dd data-name="button" data-permission="purchase.view_purchase_payment">
+                <dd data-name="button">
                     <a lay-href="purchase/purchase_payment.html">付款管理</a>
                   </dd>
-                <dd data-name="button" data-permission="purchase.view_purchase_invoice">
+                <dd data-name="button">
                     <a lay-href="purchase/purchase_invoice.html">发票管理</a>
                   </dd>
-                <dd data-name="button" data-permission="purchase.view_purchase_price_query">
+                <dd data-name="button" >
                     <a lay-href="purchase/purchase_price_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" data-permission="purchase.view_material_godown_entry">
-                  <a lay-href="purchase/material_godownentry.html">入库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="purchase.view_material_godownentry_query">
-                  <a lay-href="purchase/material_godownentry_query.html">入库查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="material.view_material_deliver">
-                  <a lay-href="material/deliver_material.html">出库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="plan.view_material_deliver_query">
-                  <a lay-href="material/deliver_material_query.html">出库查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="purchase.view_material_godown_entry_return">
-                  <a lay-href="purchase/material_godownentry_return.html">退货管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="account.view_material_godownentry_return_query">
-                  <a lay-href="purchase/material_godownentry_return_query.html">退货查询</a>
-                </dd>
-                <dd data-name="nav" data-permission="material.view_material_deliver_return">
-                  <a lay-href="material/deliver_material_return.html">退料管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="warehouse.view_material_deliver_return_query">
-                  <a lay-href="material/deliver_material_return_query.html">退料查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="warehouse.view_material_inventory">
-                  <a lay-href="material/material_inventory.html">盘存管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="warehouse.view_material_stock">
-                  <a lay-href="material/material_stock.html">库存查询</a>
-                </dd>
-                <dd data-name="nav" data-permission="product.view_material_stock_ledger">
-                  <a lay-href="material/material_stock_ledger.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" data-permission="purchase.view_consumable_godown_entry">
-                  <a lay-href="purchase/consumable_godownentry.html">入库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="purchase.view_consumable_godownentry_query">
-                  <a lay-href="purchase/consumable_godownentry_query.html">入库查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="material.view_consumable_deliver">
-                  <a lay-href="material/deliver_consumable.html">出库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="plan.view_consumable_deliver_query">
-                  <a lay-href="material/deliver_consumable_query.html">出库查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="purchase.view_consumable_godown_entry_return">
-                  <a lay-href="purchase/consumable_godownentry_return.html">退货管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="account.view_consumable_godownentry_return_query">
-                  <a lay-href="purchase/consumable_godownentry_return_query.html">退货查询</a>
-                </dd>
-                <dd data-name="nav" data-permission="material.view_consumable_deliver_return">
-                  <a lay-href="material/deliver_consumable_return.html">退料管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="purchase.view_consumable_deliver_return_query">
-                  <a lay-href="material/deliver_consumable_return_query.html">退料查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="warehouse.view_consumable_inventory">
-                  <a lay-href="material/consumable_inventory.html">盘存管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="warehouse.view_consumable_stock">
-                  <a lay-href="material/consumable_stock.html">库存查询</a>
-                </dd>
-                <dd data-name="nav" data-permission="product.view_consumable_stock_ledger">
-                  <a lay-href="material/consumable_stock_ledger.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" data-permission="goods.view_goods_godown_entry">
-                  <a lay-href="goods/goods_godownentry.html">入库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="order.view_goods_godownentry_query">
-                  <a lay-href="goods/goods_godownentry_query.html">入库查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="order.view_goods_deliver">
-                  <a lay-href="order/goods_deliver.html">出库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="order.view_goods_deliver_query">
-                  <a lay-href="order/goods_deliver_query.html">出库查询</a>
-                </dd>
-                  <dd data-name="nav" data-permission="order.view_goods_deliver_return">
-                  <a lay-href="order/goods_deliver_return.html">退库管理</a>
-                </dd>
-                  <dd data-name="nav" data-permission="order.view_goods_deliver_return_query">
-                  <a lay-href="order/goods_deliver_return_query.html">退库查询</a>
-                </dd>
-                </dd>
-                  <dd data-name="nav" data-permission="goods.view_goods_inventory">
-                  <a lay-href="goods/goods_inventory.html">盘存管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="warehouse.view_goods_stock">
-                  <a lay-href="goods/goods_stock.html">库存查询</a>
-                </dd>
-                <dd data-name="nav" data-permission="product.view_goods_stock_ledger">
-                  <a lay-href="goods/goods_stock_ledger.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" data-permission="product.view_department_ledger">
-                  <a lay-href="statistics/department_ledger.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="material.view_material">
-                  <a lay-href="material/material.html">原料产品管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="material.view_consumable">
-                  <a lay-href="material/consumable.html">耗材产品管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="goods.view_goods">
-                  <a lay-href="goods/goods.html">成品产品管理</a>
+                <dd data-name="nav">
+                  <a lay-href="option/index.html">系统选项</a>
                 </dd>
-                <dd data-name="nav" data-permission="warehouse.view_material_warehouse">
-                  <a lay-href="warehouse/material_warehouse.html">原料仓别管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="warehouse.view_consumable_warehouse">
-                  <a lay-href="warehouse/consumable_warehouse.html">耗材仓别管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="warehouse.view_goods_warehouse">
-                  <a lay-href="warehouse/goods_warehouse.html">成品仓别管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="account.view_department">
-                  <a lay-href="account/department.html">组织结构管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="foundation.view_option">
-                  <a lay-href="foundation/option.html">自定义项管理</a>
-                </dd>
-                <dd data-name="nav" data-permission="supplier.view_supplier">
+                <dd data-name="nav">
                   <a lay-href="supplier/supplier.html">供应商管理</a>
                 </dd>
-                <dd data-name="nav" data-permission="customer.view_customer">
+                <dd data-name="nav">
                   <a lay-href="customer/customer.html">客户管理</a>
                 </dd>
-                <dd data-name="nav" data-permission="account.view_user">
+                <dd data-name="nav">
                   <a lay-href="account/employee.html">人员管理</a>
                 </dd>
-                <dd data-name="nav" data-permission="foundation.view_group">
+                <dd data-name="nav">
                   <a lay-href="account/group.html">权限管理</a>
                 </dd>
-                <dd data-name="nav" data-permission="config.edit_config">
+                <dd data-name="nav">
                   <a lay-href="config/index.html">基础设置</a>
                 </dd>
               </dl>
@@ -353,20 +203,6 @@
       var name = layui.data(layui.setter.tableName)['name'];
       $('#id_username').html(name);
 
-      var permissions = layui.data(layui.setter.tableName)['permissions'];
-      $('#LAY-system-side-muen .layui-nav-child dd').each(function () {
-          var perm = $(this).data("permission");
-          //console.log(perm, permissions.indexOf(perm))
-          if(permissions.indexOf(perm) == -1){
-            $(this).remove();
-          }
-      });
-
-      $('#LAY-system-side-muen .layui-nav-item dl').each(function () {
-          if($(this).children('dd').length == 0)
-              $(this).parent().remove();
-      });
-
   });
   </script>
 </body>

+ 125 - 0
uis/views/option/edit.html

@@ -0,0 +1,125 @@
+<!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-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_type" name="type" 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>
+                  <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="checkbox" name="enable" lay-skin="switch" lay-text="是|否" checked="" value="1">
+                  </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>
+
+
+  <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
+    ,form = layui.form;
+    var id = layui.view.getParameterByName('id');
+
+    admin.req({
+        url: '/foundation/option/dict/',
+        done: function (res) {
+            var types = res.data.types;
+            var type_node = $('#id_type');
+            for (var i in types) {
+                var pid = types[i][0];
+                var value = types[i][1];
+                type_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所以这么转换
+            $('#id_type').attr('disabled', true);
+
+            form.val("component-form-element", editdata);
+        }
+    };
+
+
+    form.on('submit(component-form-element)', function(data){
+      //layer.msg(JSON.stringify(data.field));
+        if (id) {
+            var url = '/foundation/option/' + id + '/';
+            var type = 'put'
+        }else{
+            url = '/foundation/option/';
+            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>

+ 191 - 0
uis/views/option/index.html

@@ -0,0 +1,191 @@
+<!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-xs5">
+                    <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">
+                       <select id="id_type" name="type">
+                            <option value="">类别</option>
+                        </select>
+                    </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="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="edit">修改</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: '/foundation/option/dict/',
+        done: function (res) {
+            var types = res.data.types;
+            var type_node = $('#id_type');
+            for (var i in types) {
+                var pid = types[i][0];
+                var value = types[i][1];
+                type_node.append("<option value='" + pid + "'>" + value + "</option>");
+            }
+            form.render();
+        }
+    });
+
+    table.render({
+      elem: '#datagrid'
+      ,url: '/foundation/option/'
+      ,cols: [[
+        {field:'name', title:'名称',width: 200}
+       ,{field:'type_name', title:'类别',width: 120}
+       ,{field:'enable_text', title:'在用',width: 80}
+       ,{field:'notes', title:'备注'}
+        ,{width:100, 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;
+        if(obj.event === 'edit'){
+        table.editdata = data;
+        layer.open({
+          type: 2,
+          title: '修改',
+          shadeClose: false,
+          area: ['40%', '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: 'edit.html?id='+data.id
+        });
+      } else if(obj.event === 'del'){
+         layer.confirm('确定要删除吗?', function(index){
+                layer.close(index);
+                layui.admin.req({
+                    notice: true
+                    ,url: '/tenant/option/'+data.id + '/'
+                    ,type: 'delete'
+                    ,done: function(res){
+                        table.reload('datagrid',{});
+                    }
+                });
+            });
+      }
+    });
+
+    $('#btn_add').on('click', function(){
+        layer.open({
+          type: 2,
+          title: '添加',
+          shadeClose: false,
+          area: ['40%', '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: 'edit.html'
+        });
+    });
+
+    $('#btn_fill_default').on('click', function(){
+        layer.confirm('确定要创建默认的系统选项吗?', function(index){
+            layer.close(index);
+            layui.admin.req({
+                url: '/tenant/option/create_default/'
+                ,data: {}
+                ,type: 'post'
+                ,done: function(res){
+                    table.reload('datagrid',{});
+                }
+            });
+        });
+    });
+
+  });
+  </script>
+</body>
+</html>
+

+ 135 - 0
uis/views/option/search.html

@@ -0,0 +1,135 @@
+<!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">
+
+                    <div class="layui-col-md12">
+                        <div class="layui-col-sm6">
+                            <input type="text" autocomplete="off" id="keyword" placeholder="请输入名称搜索" class="layui-input"/>
+                        </div>
+                        <div class="layui-col-sm6">
+                            <button type="button" class="layui-btn" data-type="onSearchPurchase">
+                                <i class="layui-icon layui-icon-search"></i> 搜索
+                            </button>
+                        </div>
+                        <div style="clear:both;height: 5px;"></div>
+                    </div>
+
+                    <div class="layui-col-md12">
+                        <table id="dataTable" lay-filter="dataTable" class="layui-hide"></table>
+                    </div>
+
+                    <button class="layui-btn" lay-submit id="btn_search_option_ok" style="display: none">确定</button>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+  <script src="../../layuiadmin/layui/layui.js"></script>
+  <script>
+
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index' //主入口模块
+  }).use(['index', 'table'], function(){
+      var $ = layui.$
+      ,table = layui.table;
+
+      $('#btn_search_option_ok').on('click', function () {
+          var oldData = table.cache[layTableId];
+          var data = [];
+          for (var i in oldData){
+              if(oldData[i].LAY_CHECKED){
+                  data.push(oldData[i])
+              }
+          }
+          parent.layui.onSubmitChild(data);
+
+      });
+      parent.layui.submitChild = function () {
+          $("#btn_search_option_ok").click();
+      };
+
+      var tbWidth = $("#tableRes").width();
+		var layTableId = "layTable";
+		var tableIns = table.render({
+			elem: '#dataTable',
+			id: layTableId,
+			data: [],
+			width: tbWidth,
+			loading: true,
+			even: true, //不开启隔行背景
+			cols: [[
+				{title: 'ck', type: 'checkbox'},
+                {field: 'name', title: '名称', width: 150},
+                {field: 'notes', title: '备注', minWidth: 150}
+			]]
+		});
+
+		//定义事件集合
+		var active = {
+            onSearchPurchase: function(){
+              var $ = layui.$;
+              var keyword = $('#keyword').val();
+              var admin = layui.admin;
+
+              admin.req({
+                  url: '/tenant/option/search/?type=1',
+                  data: {keyword: keyword},
+                  done: function (res) {
+                      var data = res.data;
+                      var oldData = [];
+                      for (var i in data) {
+                        var item = data[i];
+                        var newRow = {
+                          id: item.value,
+                          name: item.name,
+                          notes: item.notes
+                        };
+				        oldData.push(newRow);
+                      }
+                      tableIns.reload({
+                          data : oldData
+                      });
+                  }
+              });
+            },
+		};
+
+		//激活事件
+		var activeByType = function (type, arg) {
+			if(arguments.length === 2){
+				active[type] ? active[type].call(this, arg) : '';
+			}else{
+				active[type] ? active[type].call(this) : '';
+			}
+		}
+
+		//注册按钮事件
+		$('.layui-btn[data-type]').on('click', function () {
+			var type = $(this).data('type');
+			activeByType(type);
+		});
+      active.onSearchPurchase();
+ });
+
+  </script>
+</body>
+</html>

+ 2 - 0
utils/custom_modelviewset.py

@@ -4,10 +4,12 @@ from rest_framework.viewsets import ModelViewSet
 
 from utils import response_error, response_ok
 from utils.exceptions import CustomError
+from rest_framework.permissions import IsAuthenticated
 
 from django.db import transaction
 
 class CustomModelViewSet(ModelViewSet):
+    permission_classes = [IsAuthenticated, ]
     def create(self, request, *args, **kwargs):
         try:
             with transaction.atomic():

+ 0 - 74
utils/permission.py

@@ -1,74 +0,0 @@
-# coding=utf-8
-
-from rest_framework import permissions
-
-from apps.customer.models import Customer
-from apps.WechatApplet.models import WechatApplet
-from utils.exceptions import CustomError
-from utils import response_error
-
-class IsCustomerUser(permissions.BasePermission):
-    def has_permission(self, request, view):
-        if not request.user or not request.user.is_authenticated:
-            return False
-        if not request.user.is_customer():
-            return False
-
-        appid = request.GET.get('appid', None)
-        if not appid:
-            appid = request.POST.get('appid')
-        try:
-            app = WechatApplet.getByAppid(appid)
-        except:
-            return False
-        customer = Customer.objects.filter(tenant_id=app.tenant_id, user_id=request.user.id).first()
-        if not customer:
-            return False
-        request.customer = customer
-        return True
-
-class IsTenantUser(permissions.BasePermission):
-    def has_permission(self, request, view):
-        if not request.user or not request.user.is_authenticated:
-            return False
-        return request.user.is_tenant()
-
-class IsAdministratorUser(permissions.BasePermission):
-    def has_permission(self, request, view):
-        if not request.user or not request.user.is_authenticated:
-            return False
-        return request.user.is_administrator()
-
-
-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