Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -19,6 +19,20 @@ class UsersInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
role_key = serializers.SerializerMethodField()
|
||||
dept_key = serializers.SerializerMethodField()
|
||||
|
||||
def get_dept_key(self, obj):
|
||||
if obj.dept:
|
||||
return obj.dept.key
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_role_key(self, obj):
|
||||
if obj.role.all():
|
||||
return [role.key for role in obj.role.all()]
|
||||
else:
|
||||
return []
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
@@ -35,7 +49,7 @@ class UsersInitSerializer(CustomModelSerializer):
|
||||
model = Users
|
||||
fields = ["username", "email", 'mobile', 'avatar', "name", 'gender', 'user_type', "dept", 'user_type',
|
||||
'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'creator', 'dept_belong_id',
|
||||
'password', 'last_login', 'is_superuser']
|
||||
'password', 'last_login', 'is_superuser', 'role_key' ,'dept_key']
|
||||
read_only_fields = ['id']
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
@@ -175,15 +189,21 @@ class RoleMenuInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化角色菜单(用于生成初始化json文件)
|
||||
"""
|
||||
role__key = serializers.CharField(max_length=100, required=True)
|
||||
menu__web_path = serializers.CharField(max_length=100, required=True)
|
||||
menu__component_name = serializers.CharField(max_length=100, required=True, allow_blank=True)
|
||||
role__key = serializers.CharField(source='role.key')
|
||||
menu__web_path = serializers.CharField(source='menu.web_path')
|
||||
menu__component_name = serializers.CharField(source='menu.component_name', allow_blank=True)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
init_data = self.initial_data
|
||||
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||
menu_id = Menu.objects.filter(web_path=init_data['menu__web_path'], component_name=init_data['menu__component_name']).first()
|
||||
validated_data['role'] = role_id
|
||||
validated_data['menu'] = menu_id
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
def create(self, validated_data):
|
||||
init_data = self.initial_data
|
||||
validated_data.pop('menu__web_path')
|
||||
validated_data.pop('menu__component_name')
|
||||
validated_data.pop('role__key')
|
||||
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||
menu_id = Menu.objects.filter(web_path=init_data['menu__web_path'], component_name=init_data['menu__component_name']).first()
|
||||
validated_data['role'] = role_id
|
||||
@@ -192,7 +212,7 @@ class RoleMenuInitSerializer(CustomModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuPermission
|
||||
fields = ['role__key', 'menu__web_path', 'menu__component_name', 'creator', 'dept_belong_id']
|
||||
fields = ['role__key', 'menu__web_path', 'menu__component_name','creator', 'dept_belong_id']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'role': {'required': False},
|
||||
@@ -206,14 +226,22 @@ class RoleMenuButtonInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化角色菜单按钮(用于生成初始化json文件)
|
||||
"""
|
||||
role__key = serializers.CharField(max_length=100, required=True)
|
||||
menu_button__value = serializers.CharField(max_length=100, required=True)
|
||||
role__key = serializers.CharField(source='role.key')
|
||||
menu_button__value = serializers.CharField(source='menu_button.value')
|
||||
data_range = serializers.CharField(max_length=100, required=False)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
init_data = self.initial_data
|
||||
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||
menu_button_id = MenuButton.objects.filter(value=init_data['menu_button__value']).first()
|
||||
validated_data['role'] = role_id
|
||||
validated_data['menu_button'] = menu_button_id
|
||||
instance = super().create(validated_data)
|
||||
instance.dept.set([])
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
def create(self, validated_data):
|
||||
init_data = self.initial_data
|
||||
validated_data.pop('menu_button__value')
|
||||
validated_data.pop('role__key')
|
||||
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||
menu_button_id = MenuButton.objects.filter(value=init_data['menu_button__value']).first()
|
||||
validated_data['role'] = role_id
|
||||
@@ -223,7 +251,7 @@ class RoleMenuButtonInitSerializer(CustomModelSerializer):
|
||||
return instance
|
||||
|
||||
def save(self, **kwargs):
|
||||
if self.instance and self.initial_data.get('reset'):
|
||||
if not self.instance or self.initial_data.get('reset'):
|
||||
return super().save(**kwargs)
|
||||
return self.instance
|
||||
|
||||
|
||||
@@ -672,6 +672,53 @@
|
||||
"model": "ApiWhiteList"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "下载中心",
|
||||
"icon": "ele-Download",
|
||||
"sort": 9,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/downloadCenter",
|
||||
"component": "system/downloadCenter/index",
|
||||
"component_name": "downloadCenter",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 277,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "Search",
|
||||
"api": "/api/system/downloadCenter/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "Retrieve",
|
||||
"api": "/api/system/downloadCenter/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "Create",
|
||||
"api": "/api/system/downloadCenter/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "Update",
|
||||
"api": "/api/system/downloadCenter/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "Delete",
|
||||
"api": "/api/system/downloadCenter/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"menu_button": [],
|
||||
|
||||
@@ -10,7 +10,7 @@ django.setup()
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from application.settings import BASE_DIR
|
||||
from dvadmin.system.models import Menu, Users, Dept, Role, ApiWhiteList, Dictionary, SystemConfig
|
||||
from dvadmin.system.models import Menu, Users, Dept, Role, ApiWhiteList, Dictionary, SystemConfig, RoleMenuButtonPermission, RoleMenuPermission
|
||||
from dvadmin.system.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
|
||||
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
|
||||
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
|
||||
@@ -57,6 +57,12 @@ class Command(BaseCommand):
|
||||
def generate_system_config(self):
|
||||
self.serializer_data(SystemConfigInitSerializer, SystemConfig.objects.filter(parent_id__isnull=True))
|
||||
|
||||
def generate_role_menu(self):
|
||||
self.serializer_data(RoleMenuInitSerializer, RoleMenuPermission.objects.all())
|
||||
|
||||
def generate_role_menu_button(self):
|
||||
self.serializer_data(RoleMenuButtonInitSerializer, RoleMenuButtonPermission.objects.all())
|
||||
|
||||
def handle(self, *args, **options):
|
||||
generate_name = options.get('generate_name')
|
||||
generate_name_dict = {
|
||||
@@ -67,6 +73,8 @@ class Command(BaseCommand):
|
||||
"api_white_list": self.generate_api_white_list,
|
||||
"dictionary": self.generate_dictionary,
|
||||
"system_config": self.generate_system_config,
|
||||
"role_menu": self.generate_role_menu,
|
||||
"role_menu_button": self.generate_role_menu_button,
|
||||
}
|
||||
if not generate_name:
|
||||
for ele in generate_name_dict.keys():
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import hashlib
|
||||
import os
|
||||
from time import time
|
||||
from pathlib import PurePosixPath
|
||||
|
||||
from django.contrib.auth.models import AbstractUser, UserManager
|
||||
from django.db import models
|
||||
@@ -7,8 +9,8 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||
from application import dispatch
|
||||
from dvadmin.utils.models import CoreModel, table_prefix, get_custom_app_models
|
||||
|
||||
|
||||
class Role(CoreModel):
|
||||
from dvadmin3_flow.base_model import FlowBaseModel
|
||||
class Role(CoreModel,FlowBaseModel):
|
||||
name = models.CharField(max_length=64, verbose_name="角色名称", help_text="角色名称")
|
||||
key = models.CharField(max_length=64, unique=True, verbose_name="权限字符", help_text="权限字符")
|
||||
sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序")
|
||||
@@ -71,6 +73,7 @@ class Users(CoreModel, AbstractUser):
|
||||
help_text="关联部门",
|
||||
)
|
||||
login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数")
|
||||
pwd_change_count = models.IntegerField(default=0,blank=True, verbose_name="密码修改次数", help_text="密码修改次数")
|
||||
objects = CustomUserManager()
|
||||
|
||||
def set_password(self, raw_password):
|
||||
@@ -119,6 +122,27 @@ class Dept(CoreModel):
|
||||
help_text="上级部门",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _recursion(cls, instance, parent, result):
|
||||
new_instance = getattr(instance, parent, None)
|
||||
res = []
|
||||
data = getattr(instance, result, None)
|
||||
if data:
|
||||
res.append(data)
|
||||
if new_instance:
|
||||
array = cls._recursion(new_instance, parent, result)
|
||||
res += array
|
||||
return res
|
||||
|
||||
@classmethod
|
||||
def get_region_name(cls, obj):
|
||||
"""
|
||||
获取某个用户的递归所有部门名称
|
||||
"""
|
||||
dept_name_all = cls._recursion(obj, "parent", "name")
|
||||
dept_name_all.reverse()
|
||||
return "/".join(dept_name_all)
|
||||
|
||||
@classmethod
|
||||
def recursion_all_dept(cls, dept_id: int, dept_all_list=None, dept_list=None):
|
||||
"""
|
||||
@@ -405,6 +429,18 @@ class FileList(CoreModel):
|
||||
mime_type = models.CharField(max_length=100, blank=True, verbose_name="Mime类型", help_text="Mime类型")
|
||||
size = models.CharField(max_length=36, blank=True, verbose_name="文件大小", help_text="文件大小")
|
||||
md5sum = models.CharField(max_length=36, blank=True, verbose_name="文件md5", help_text="文件md5")
|
||||
UPLOAD_METHOD_CHOIDES = (
|
||||
(0, '默认上传'),
|
||||
(1, '文件选择器上传'),
|
||||
)
|
||||
upload_method = models.SmallIntegerField(default=0, blank=True, null=True, choices=UPLOAD_METHOD_CHOIDES, verbose_name='上传方式', help_text='上传方式')
|
||||
FILE_TYPE_CHOIDES = (
|
||||
(0, '图片'),
|
||||
(1, '视频'),
|
||||
(2, '音频'),
|
||||
(3, '其他'),
|
||||
)
|
||||
file_type = models.SmallIntegerField(default=3, choices=FILE_TYPE_CHOIDES, blank=True, null=True, verbose_name='文件类型', help_text='文件类型')
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.md5sum: # file is new
|
||||
@@ -595,3 +631,41 @@ class MessageCenterTargetUser(CoreModel):
|
||||
db_table = table_prefix + "message_center_target_user"
|
||||
verbose_name = "消息中心目标用户表"
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
def media_file_name_downloadcenter(instance:'DownloadCenter', filename):
|
||||
h = instance.md5sum
|
||||
basename, ext = os.path.splitext(filename)
|
||||
return PurePosixPath("files", "dlct", h[:1], h[1:2], basename + '-' + str(time()).replace('.', '') + ext.lower())
|
||||
|
||||
|
||||
class DownloadCenter(CoreModel):
|
||||
TASK_STATUS_CHOICES = [
|
||||
(0, '任务已创建'),
|
||||
(1, '任务进行中'),
|
||||
(2, '任务完成'),
|
||||
(3, '任务失败'),
|
||||
]
|
||||
task_name = models.CharField(max_length=255, verbose_name="任务名称", help_text="任务名称")
|
||||
task_status = models.SmallIntegerField(default=0, choices=TASK_STATUS_CHOICES, verbose_name='是否可下载', help_text='是否可下载')
|
||||
file_name = models.CharField(max_length=255, null=True, blank=True, verbose_name="文件名", help_text="文件名")
|
||||
url = models.FileField(upload_to=media_file_name_downloadcenter, null=True, blank=True)
|
||||
size = models.BigIntegerField(default=0, verbose_name="文件大小", help_text="文件大小")
|
||||
md5sum = models.CharField(max_length=36, null=True, blank=True, verbose_name="文件md5", help_text="文件md5")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.url:
|
||||
if not self.md5sum: # file is new
|
||||
md5 = hashlib.md5()
|
||||
for chunk in self.url.chunks():
|
||||
md5.update(chunk)
|
||||
self.md5sum = md5.hexdigest()
|
||||
if not self.size:
|
||||
self.size = self.url.size
|
||||
super(DownloadCenter, self).save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "download_center"
|
||||
verbose_name = "下载中心"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
12
backend/dvadmin/system/signals.py
Normal file
12
backend/dvadmin/system/signals.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.dispatch import Signal
|
||||
# 初始化信号
|
||||
pre_init_complete = Signal()
|
||||
detail_init_complete = Signal()
|
||||
post_init_complete = Signal()
|
||||
# 租户初始化信号
|
||||
pre_tenants_init_complete = Signal()
|
||||
detail_tenants_init_complete = Signal()
|
||||
post_tenants_init_complete = Signal()
|
||||
post_tenants_all_init_complete = Signal()
|
||||
# 租户创建完成信号
|
||||
tenants_create_complete = Signal()
|
||||
107
backend/dvadmin/system/tasks.py
Normal file
107
backend/dvadmin/system/tasks.py
Normal file
@@ -0,0 +1,107 @@
|
||||
from hashlib import md5
|
||||
from io import BytesIO
|
||||
from datetime import datetime
|
||||
from time import sleep
|
||||
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.worksheet.table import Table, TableStyleInfo
|
||||
from openpyxl.utils import get_column_letter
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
from application.celery import app
|
||||
from dvadmin.system.models import DownloadCenter
|
||||
|
||||
def is_number(num):
|
||||
try:
|
||||
float(num)
|
||||
return True
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import unicodedata
|
||||
unicodedata.numeric(num)
|
||||
return True
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
return False
|
||||
|
||||
def get_string_len(string):
|
||||
"""
|
||||
获取字符串最大长度
|
||||
:param string:
|
||||
:return:
|
||||
"""
|
||||
length = 4
|
||||
if string is None:
|
||||
return length
|
||||
if is_number(string):
|
||||
return length
|
||||
for char in string:
|
||||
length += 2.1 if ord(char) > 256 else 1
|
||||
return round(length, 1) if length <= 50 else 50
|
||||
|
||||
@app.task
|
||||
def async_export_data(data: list, filename: str, dcid: int, export_field_label: dict):
|
||||
instance = DownloadCenter.objects.get(pk=dcid)
|
||||
instance.task_status = 1
|
||||
instance.save()
|
||||
sleep(2)
|
||||
try:
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
header_data = ["序号", *export_field_label.values()]
|
||||
hidden_header = ["#", *export_field_label.keys()]
|
||||
df_len_max = [get_string_len(ele) for ele in header_data]
|
||||
row = get_column_letter(len(export_field_label) + 1)
|
||||
column = 1
|
||||
ws.append(header_data)
|
||||
for index, results in enumerate(data):
|
||||
results_list = []
|
||||
for h_index, h_item in enumerate(hidden_header):
|
||||
for key, val in results.items():
|
||||
if key == h_item:
|
||||
if val is None or val == "":
|
||||
results_list.append("")
|
||||
elif isinstance(val, datetime):
|
||||
val = val.strftime("%Y-%m-%d %H:%M:%S")
|
||||
results_list.append(val)
|
||||
else:
|
||||
results_list.append(val)
|
||||
# 计算最大列宽度
|
||||
result_column_width = get_string_len(val)
|
||||
if h_index != 0 and result_column_width > df_len_max[h_index]:
|
||||
df_len_max[h_index] = result_column_width
|
||||
ws.append([index + 1, *results_list])
|
||||
column += 1
|
||||
# 更新列宽
|
||||
for index, width in enumerate(df_len_max):
|
||||
ws.column_dimensions[get_column_letter(index + 1)].width = width
|
||||
tab = Table(displayName="Table", ref=f"A1:{row}{column}") # 名称管理器
|
||||
style = TableStyleInfo(
|
||||
name="TableStyleLight11",
|
||||
showFirstColumn=True,
|
||||
showLastColumn=True,
|
||||
showRowStripes=True,
|
||||
showColumnStripes=True,
|
||||
)
|
||||
tab.tableStyleInfo = style
|
||||
ws.add_table(tab)
|
||||
stream = BytesIO()
|
||||
wb.save(stream)
|
||||
stream.seek(0)
|
||||
s = md5()
|
||||
while True:
|
||||
chunk = stream.read(1024)
|
||||
if not chunk:
|
||||
break
|
||||
s.update(chunk)
|
||||
stream.seek(0)
|
||||
instance.md5sum = s.hexdigest()
|
||||
instance.file_name = filename
|
||||
instance.url.save(filename, ContentFile(stream.read()))
|
||||
instance.task_status = 2
|
||||
except Exception as e:
|
||||
instance.task_status = 3
|
||||
instance.description = str(e)[:250]
|
||||
instance.save()
|
||||
@@ -18,6 +18,7 @@ from dvadmin.system.views.role_menu_button_permission import RoleMenuButtonPermi
|
||||
from dvadmin.system.views.system_config import SystemConfigViewSet
|
||||
from dvadmin.system.views.user import UserViewSet
|
||||
from dvadmin.system.views.menu_field import MenuFieldViewSet
|
||||
from dvadmin.system.views.download_center import DownloadCenterViewSet
|
||||
|
||||
system_url = routers.SimpleRouter()
|
||||
system_url.register(r'menu', MenuViewSet)
|
||||
@@ -36,6 +37,7 @@ system_url.register(r'role_menu_button_permission', RoleMenuButtonPermissionView
|
||||
system_url.register(r'role_menu_permission', RoleMenuPermissionViewSet)
|
||||
system_url.register(r'column', MenuFieldViewSet)
|
||||
system_url.register(r'login_log', LoginLogViewSet)
|
||||
system_url.register(r'download_center', DownloadCenterViewSet)
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
@@ -47,7 +49,7 @@ urlpatterns = [
|
||||
path('system_config/get_relation_info/', SystemConfigViewSet.as_view({'get': 'get_relation_info'})),
|
||||
# path('login_log/', LoginLogViewSet.as_view({'get': 'list'})),
|
||||
# path('login_log/<int:pk>/', LoginLogViewSet.as_view({'get': 'retrieve'})),
|
||||
path('dept_lazy_tree/', DeptViewSet.as_view({'get': 'dept_lazy_tree'})),
|
||||
# path('dept_lazy_tree/', DeptViewSet.as_view({'get': 'dept_lazy_tree'})),
|
||||
path('clause/privacy.html', PrivacyView.as_view()),
|
||||
path('clause/terms_service.html', TermsServiceView.as_view()),
|
||||
]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pypinyin
|
||||
from django.db.models import Q
|
||||
from rest_framework import serializers
|
||||
|
||||
@@ -15,6 +16,11 @@ class AreaSerializer(CustomModelSerializer):
|
||||
"""
|
||||
pcode_count = serializers.SerializerMethodField(read_only=True)
|
||||
hasChild = serializers.SerializerMethodField()
|
||||
pcode_info = serializers.SerializerMethodField()
|
||||
|
||||
def get_pcode_info(self, instance):
|
||||
pcode = Area.objects.filter(code=instance.pcode_id).values("name", "code")
|
||||
return pcode
|
||||
|
||||
def get_pcode_count(self, instance: Area):
|
||||
return Area.objects.filter(pcode=instance).count()
|
||||
@@ -36,6 +42,18 @@ class AreaCreateUpdateSerializer(CustomModelSerializer):
|
||||
地区管理 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
def to_internal_value(self, data):
|
||||
pinyin = ''.join([''.join(i) for i in pypinyin.pinyin(data["name"], style=pypinyin.NORMAL)])
|
||||
data["level"] = 1
|
||||
data["pinyin"] = pinyin
|
||||
data["initials"] = pinyin[0].upper() if pinyin else "#"
|
||||
pcode = data["pcode"] if 'pcode' in data else None
|
||||
if pcode:
|
||||
pcode = Area.objects.get(pk=pcode)
|
||||
data["pcode"] = pcode.code
|
||||
data["level"] = pcode.level + 1
|
||||
return super().to_internal_value(data)
|
||||
|
||||
class Meta:
|
||||
model = Area
|
||||
fields = '__all__'
|
||||
@@ -52,20 +70,28 @@ class AreaViewSet(CustomModelViewSet, FieldPermissionMixin):
|
||||
"""
|
||||
queryset = Area.objects.all()
|
||||
serializer_class = AreaSerializer
|
||||
create_serializer_class = AreaCreateUpdateSerializer
|
||||
update_serializer_class = AreaCreateUpdateSerializer
|
||||
extra_filter_class = []
|
||||
|
||||
def get_queryset(self):
|
||||
def list(self, request, *args, **kwargs):
|
||||
self.request.query_params._mutable = True
|
||||
params = self.request.query_params
|
||||
pcode = params.get('pcode', None)
|
||||
page = params.get('page', None)
|
||||
limit = params.get('limit', None)
|
||||
if page:
|
||||
del params['page']
|
||||
if limit:
|
||||
del params['limit']
|
||||
if params and pcode:
|
||||
queryset = self.queryset.filter(enable=True, pcode=pcode)
|
||||
else:
|
||||
known_params = {'page', 'limit', 'pcode'}
|
||||
# 使用集合操作检查是否有未知参数
|
||||
other_params_exist = any(param not in known_params for param in params)
|
||||
if other_params_exist:
|
||||
queryset = self.queryset.filter(enable=True)
|
||||
return queryset
|
||||
else:
|
||||
pcode = params.get('pcode', None)
|
||||
params['limit'] = 999
|
||||
if params and pcode:
|
||||
queryset = self.queryset.filter(enable=True, pcode=pcode)
|
||||
else:
|
||||
queryset = self.queryset.filter(enable=True, level=1)
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
serializer = self.get_serializer(page, many=True, request=request)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
serializer = self.get_serializer(queryset, many=True, request=request)
|
||||
return SuccessResponse(data=serializer.data, msg="获取成功")
|
||||
|
||||
49
backend/dvadmin/system/views/download_center.py
Normal file
49
backend/dvadmin/system/views/download_center.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from rest_framework import serializers
|
||||
from django.conf import settings
|
||||
from django_filters.rest_framework import FilterSet, CharFilter
|
||||
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
from dvadmin.system.models import DownloadCenter
|
||||
|
||||
|
||||
class DownloadCenterSerializer(CustomModelSerializer):
|
||||
url = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def get_url(self, instance):
|
||||
if self.request.query_params.get('prefix'):
|
||||
if settings.ENVIRONMENT in ['local']:
|
||||
prefix = 'http://127.0.0.1:8000'
|
||||
elif settings.ENVIRONMENT in ['test']:
|
||||
prefix = 'http://{host}/api'.format(host=self.request.get_host())
|
||||
else:
|
||||
prefix = 'https://{host}/api'.format(host=self.request.get_host())
|
||||
return (f'{prefix}/media/{str(instance.url)}')
|
||||
return f'media/{str(instance.url)}'
|
||||
|
||||
class Meta:
|
||||
model = DownloadCenter
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class DownloadCenterFilterSet(FilterSet):
|
||||
task_name = CharFilter(field_name='task_name', lookup_expr='icontains')
|
||||
file_name = CharFilter(field_name='file_name', lookup_expr='icontains')
|
||||
|
||||
class Meta:
|
||||
model = DownloadCenter
|
||||
fields = ['task_status', 'task_name', 'file_name']
|
||||
|
||||
|
||||
class DownloadCenterViewSet(CustomModelViewSet):
|
||||
queryset = DownloadCenter.objects.all()
|
||||
serializer_class = DownloadCenterSerializer
|
||||
filter_class = DownloadCenterFilterSet
|
||||
permission_classes = []
|
||||
extra_filter_class = []
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
return super().get_queryset()
|
||||
return super().get_queryset().filter(creator=self.request.user)
|
||||
@@ -1,12 +1,15 @@
|
||||
import hashlib
|
||||
import mimetypes
|
||||
|
||||
import django_filters
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from application import dispatch
|
||||
from dvadmin.system.models import FileList
|
||||
from dvadmin.utils.json_response import DetailResponse
|
||||
from dvadmin.utils.json_response import DetailResponse, SuccessResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
@@ -15,8 +18,17 @@ class FileSerializer(CustomModelSerializer):
|
||||
url = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def get_url(self, instance):
|
||||
base_url = f"{self.request.scheme}://{self.request.get_host()}/"
|
||||
return base_url + (instance.file_url or (f'media/{str(instance.url)}'))
|
||||
if self.request.query_params.get('prefix'):
|
||||
if settings.ENVIRONMENT in ['local']:
|
||||
prefix = 'http://127.0.0.1:8000'
|
||||
elif settings.ENVIRONMENT in ['test']:
|
||||
prefix = 'http://{host}/api'.format(host=self.request.get_host())
|
||||
else:
|
||||
prefix = 'https://{host}/api'.format(host=self.request.get_host())
|
||||
if instance.file_url:
|
||||
return instance.file_url if instance.file_url.startswith('http') else f"{prefix}/{instance.file_url}"
|
||||
return (f'{prefix}/media/{str(instance.url)}')
|
||||
return instance.file_url or (f'media/{str(instance.url)}')
|
||||
|
||||
class Meta:
|
||||
model = FileList
|
||||
@@ -35,6 +47,8 @@ class FileSerializer(CustomModelSerializer):
|
||||
validated_data['md5sum'] = md5.hexdigest()
|
||||
validated_data['engine'] = file_engine
|
||||
validated_data['mime_type'] = file.content_type
|
||||
ft = {'image':0,'video':1,'audio':2}.get(file.content_type.split('/')[0], None)
|
||||
validated_data['file_type'] = 3 if ft is None else ft
|
||||
if file_backup:
|
||||
validated_data['url'] = file
|
||||
if file_engine == 'oss':
|
||||
@@ -64,6 +78,22 @@ class FileSerializer(CustomModelSerializer):
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class FileAllSerializer(CustomModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = FileList
|
||||
fields = ['id', 'name']
|
||||
|
||||
|
||||
class FileFilter(django_filters.FilterSet):
|
||||
name = django_filters.CharFilter(field_name="name", lookup_expr="icontains", help_text="文件名")
|
||||
mime_type = django_filters.CharFilter(field_name="mime_type", lookup_expr="icontains", help_text="文件类型")
|
||||
|
||||
class Meta:
|
||||
model = FileList
|
||||
fields = ['name', 'mime_type', 'upload_method', 'file_type']
|
||||
|
||||
|
||||
class FileViewSet(CustomModelViewSet):
|
||||
"""
|
||||
文件管理接口
|
||||
@@ -75,5 +105,22 @@ class FileViewSet(CustomModelViewSet):
|
||||
"""
|
||||
queryset = FileList.objects.all()
|
||||
serializer_class = FileSerializer
|
||||
filter_fields = ['name', ]
|
||||
permission_classes = []
|
||||
filter_class = FileFilter
|
||||
permission_classes = []
|
||||
|
||||
@action(methods=['GET'], detail=False)
|
||||
def get_all(self, request):
|
||||
data1 = self.get_serializer(self.get_queryset(), many=True).data
|
||||
data2 = []
|
||||
if dispatch.is_tenants_mode():
|
||||
from django_tenants.utils import schema_context
|
||||
with schema_context('public'):
|
||||
data2 = self.get_serializer(FileList.objects.all(), many=True).data
|
||||
return DetailResponse(data=data2+data1)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
if self.request.query_params.get('system', 'False') == 'True' and dispatch.is_tenants_mode():
|
||||
from django_tenants.utils import schema_context
|
||||
with schema_context('public'):
|
||||
return super().list(request, *args, **kwargs)
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
@@ -4,12 +4,15 @@ from datetime import datetime, timedelta
|
||||
from captcha.views import CaptchaStore, captcha_image
|
||||
from django.contrib import auth
|
||||
from django.contrib.auth import login
|
||||
from django.contrib.auth.hashers import check_password, make_password
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
||||
@@ -97,16 +100,17 @@ class LoginSerializer(TokenObtainPairSerializer):
|
||||
# 必须重置用户名为username,否则使用邮箱手机号登录会提示密码错误
|
||||
attrs['username'] = user.username
|
||||
data = super().validate(attrs)
|
||||
data["username"] = self.user.username
|
||||
data["name"] = self.user.name
|
||||
data["userId"] = self.user.id
|
||||
data["avatar"] = self.user.avatar
|
||||
data['user_type'] = self.user.user_type
|
||||
data['pwd_change_count'] = self.user.pwd_change_count
|
||||
dept = getattr(self.user, 'dept', None)
|
||||
if dept:
|
||||
data['dept_info'] = {
|
||||
'dept_id': dept.id,
|
||||
'dept_name': dept.name,
|
||||
|
||||
}
|
||||
role = getattr(self.user, 'role', None)
|
||||
if role:
|
||||
@@ -124,6 +128,7 @@ class LoginSerializer(TokenObtainPairSerializer):
|
||||
user.is_active = False
|
||||
user.save()
|
||||
raise CustomValidationError("账号已被锁定,联系管理员解锁")
|
||||
user.save()
|
||||
count = 5 - user.login_error_count
|
||||
raise CustomValidationError(f"账号/密码错误;重试{count}次后将被锁定~")
|
||||
|
||||
|
||||
@@ -120,11 +120,11 @@ class MenuViewSet(CustomModelViewSet):
|
||||
"""用于前端获取当前角色的路由"""
|
||||
user = request.user
|
||||
if user.is_superuser:
|
||||
queryset = self.queryset.filter(status=1)
|
||||
queryset = self.queryset.filter(status=1).order_by("sort")
|
||||
else:
|
||||
role_list = user.role.values_list('id', flat=True)
|
||||
menu_list = RoleMenuPermission.objects.filter(role__in=role_list).values_list('menu_id', flat=True)
|
||||
queryset = Menu.objects.filter(id__in=menu_list)
|
||||
queryset = Menu.objects.filter(id__in=menu_list).order_by("sort")
|
||||
serializer = WebRouterSerializer(queryset, many=True, request=request)
|
||||
data = serializer.data
|
||||
return SuccessResponse(data=data, total=len(data), msg="获取成功")
|
||||
|
||||
@@ -36,6 +36,8 @@ class MessageCenterSerializer(CustomModelSerializer):
|
||||
return serializer.data
|
||||
|
||||
def get_user_info(self, instance, parsed_query):
|
||||
if instance.target_type in (1,2,3):
|
||||
return []
|
||||
users = instance.target_user.all()
|
||||
# You can do what ever you want in here
|
||||
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||
@@ -106,6 +108,8 @@ class MessageCenterTargetUserListSerializer(CustomModelSerializer):
|
||||
return serializer.data
|
||||
|
||||
def get_user_info(self, instance, parsed_query):
|
||||
if instance.target_type in (1,2,3):
|
||||
return []
|
||||
users = instance.target_user.all()
|
||||
# You can do what ever you want in here
|
||||
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||
|
||||
@@ -10,22 +10,29 @@ from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from dvadmin.system.models import Role, Menu, MenuButton, Dept
|
||||
from dvadmin.system.models import Role, Menu, MenuButton, Dept, Users
|
||||
from dvadmin.system.views.dept import DeptSerializer
|
||||
from dvadmin.system.views.menu import MenuSerializer
|
||||
from dvadmin.system.views.menu_button import MenuButtonSerializer
|
||||
from dvadmin.utils.crud_mixin import FastCrudMixin
|
||||
from dvadmin.utils.field_permission import FieldPermissionMixin
|
||||
from dvadmin.utils.json_response import SuccessResponse, DetailResponse
|
||||
from dvadmin.utils.json_response import SuccessResponse, DetailResponse, ErrorResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.validator import CustomUniqueValidator
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
from dvadmin.utils.permission import CustomPermission
|
||||
|
||||
|
||||
class RoleSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色-序列化器
|
||||
"""
|
||||
users = serializers.SerializerMethodField()
|
||||
|
||||
@staticmethod
|
||||
def get_users(instance):
|
||||
users = instance.users_set.exclude(id=1).values('id', 'name', 'dept__name')
|
||||
return users
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
@@ -101,7 +108,6 @@ class MenuButtonPermissionSerializer(CustomModelSerializer):
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
|
||||
class RoleViewSet(CustomModelViewSet, FastCrudMixin,FieldPermissionMixin):
|
||||
"""
|
||||
角色管理接口
|
||||
@@ -116,3 +122,82 @@ class RoleViewSet(CustomModelViewSet, FastCrudMixin,FieldPermissionMixin):
|
||||
create_serializer_class = RoleCreateUpdateSerializer
|
||||
update_serializer_class = RoleCreateUpdateSerializer
|
||||
search_fields = ['name', 'key']
|
||||
|
||||
@action(methods=['PUT'], detail=True, permission_classes=[IsAuthenticated])
|
||||
def set_role_users(self, request, pk):
|
||||
"""
|
||||
设置 角色-用户
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
data = request.data
|
||||
direction = data.get('direction')
|
||||
movedKeys = data.get('movedKeys')
|
||||
role = Role.objects.get(pk=pk)
|
||||
if direction == "left":
|
||||
# left : 移除用户权限
|
||||
role.users_set.remove(*movedKeys)
|
||||
else:
|
||||
# right : 添加用户权限
|
||||
role.users_set.add(*movedKeys)
|
||||
serializer = RoleSerializer(role)
|
||||
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated, CustomPermission])
|
||||
def get_role_users(self, request):
|
||||
"""
|
||||
获取角色已授权、未授权的用户
|
||||
已授权的用户:1
|
||||
未授权的用户:0
|
||||
"""
|
||||
role_id = request.query_params.get('role_id', None)
|
||||
|
||||
if not role_id:
|
||||
return ErrorResponse(msg="请选择角色")
|
||||
|
||||
if request.query_params.get('authorized', 0) == "1":
|
||||
queryset = Users.objects.filter(role__id=role_id).exclude(is_superuser=True)
|
||||
else:
|
||||
queryset = Users.objects.exclude(role__id=role_id).exclude(is_superuser=True)
|
||||
|
||||
if name := request.query_params.get('name', None):
|
||||
queryset = queryset.filter(name__icontains=name)
|
||||
|
||||
if dept := request.query_params.get('dept', None):
|
||||
queryset = queryset.filter(dept=dept)
|
||||
|
||||
page = self.paginate_queryset(queryset.values('id', 'name', 'dept__name'))
|
||||
if page is not None:
|
||||
return self.get_paginated_response(page)
|
||||
|
||||
return SuccessResponse(data=page)
|
||||
|
||||
@action(methods=['DELETE'], detail=True, permission_classes=[IsAuthenticated, CustomPermission])
|
||||
def remove_role_user(self, request, pk):
|
||||
"""
|
||||
角色-删除用户
|
||||
"""
|
||||
user_id = request.data.get('user_id', None)
|
||||
|
||||
if not user_id:
|
||||
return ErrorResponse(msg="请选择用户")
|
||||
|
||||
role = self.get_object()
|
||||
role.users_set.remove(*user_id)
|
||||
|
||||
return SuccessResponse(msg="删除成功")
|
||||
|
||||
@action(methods=['POST'], detail=True, permission_classes=[IsAuthenticated, CustomPermission])
|
||||
def add_role_users(self, request, pk):
|
||||
"""
|
||||
角色-添加用户
|
||||
"""
|
||||
users_id = request.data.get('users_id', None)
|
||||
|
||||
if not users_id:
|
||||
return ErrorResponse(msg="请选择用户")
|
||||
|
||||
role = self.get_object()
|
||||
role.users_set.add(*users_id)
|
||||
|
||||
return DetailResponse(msg="添加成功")
|
||||
|
||||
@@ -6,24 +6,20 @@
|
||||
@Created on: 2021/6/3 003 0:30
|
||||
@Remark: 菜单按钮管理
|
||||
"""
|
||||
from django.db.models import F, Subquery, OuterRef, Exists, BooleanField, Q, Case, Value, When
|
||||
from django.db.models.functions import Coalesce
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.fields import ListField
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission, FieldPermission, \
|
||||
MenuField
|
||||
from dvadmin.system.views.menu import MenuSerializer
|
||||
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
|
||||
from dvadmin.system.models import RoleMenuButtonPermission, Menu, Dept, MenuButton, RoleMenuPermission, \
|
||||
MenuField, FieldPermission
|
||||
from dvadmin.utils.json_response import DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单按钮-序列化器
|
||||
角色-菜单-按钮-权限 查询序列化
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
@@ -34,7 +30,7 @@ class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
|
||||
|
||||
class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化菜单按钮-序列化器
|
||||
角色-菜单-按钮-权限 创建/修改序列化
|
||||
"""
|
||||
menu_button__name = serializers.CharField(source='menu_button.name', read_only=True)
|
||||
menu_button__value = serializers.CharField(source='menu_button.value', read_only=True)
|
||||
@@ -45,63 +41,99 @@ class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer):
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class RoleButtonPermissionSerializer(CustomModelSerializer):
|
||||
class RoleMenuSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色按钮权限
|
||||
角色-菜单 序列化
|
||||
"""
|
||||
isCheck = serializers.SerializerMethodField()
|
||||
data_range = serializers.SerializerMethodField()
|
||||
|
||||
def get_isCheck(self, instance):
|
||||
params = self.request.query_params
|
||||
data = self.request.data
|
||||
return RoleMenuPermission.objects.filter(
|
||||
menu_id=instance.id,
|
||||
role_id=params.get('roleId', data.get('roleId')),
|
||||
).exists()
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = ["id", "name", "parent", "is_catalog", "isCheck"]
|
||||
|
||||
|
||||
class RoleMenuButtonSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色-菜单-按钮 序列化
|
||||
"""
|
||||
isCheck = serializers.SerializerMethodField()
|
||||
data_range = serializers.SerializerMethodField()
|
||||
role_menu_btn_perm_id = serializers.SerializerMethodField()
|
||||
dept = serializers.SerializerMethodField()
|
||||
|
||||
def get_isCheck(self, instance):
|
||||
params = self.request.query_params
|
||||
data = self.request.data
|
||||
return RoleMenuButtonPermission.objects.filter(
|
||||
menu_button__id=instance['id'],
|
||||
role__id=params.get('role'),
|
||||
menu_button_id=instance.id,
|
||||
role_id=params.get('roleId', data.get('roleId')),
|
||||
).exists()
|
||||
|
||||
def get_data_range(self, instance):
|
||||
params = self.request.query_params
|
||||
obj = RoleMenuButtonPermission.objects.filter(
|
||||
menu_button__id=instance['id'],
|
||||
role__id=params.get('role'),
|
||||
).first()
|
||||
obj = self.get_role_menu_btn_prem(instance)
|
||||
if obj is None:
|
||||
return None
|
||||
return obj.data_range
|
||||
|
||||
def get_role_menu_btn_perm_id(self, instance):
|
||||
obj = self.get_role_menu_btn_prem(instance)
|
||||
if obj is None:
|
||||
return None
|
||||
return obj.id
|
||||
|
||||
def get_dept(self, instance):
|
||||
obj = self.get_role_menu_btn_prem(instance)
|
||||
if obj is None:
|
||||
return None
|
||||
return obj.dept.all().values_list('id', flat=True)
|
||||
|
||||
def get_role_menu_btn_prem(self, instance):
|
||||
params = self.request.query_params
|
||||
data = self.request.data
|
||||
obj = RoleMenuButtonPermission.objects.filter(
|
||||
menu_button_id=instance.id,
|
||||
role_id=params.get('roleId', data.get('roleId')),
|
||||
).first()
|
||||
return obj
|
||||
|
||||
class Meta:
|
||||
model = MenuButton
|
||||
fields = ['id', 'name', 'value', 'isCheck', 'data_range']
|
||||
|
||||
|
||||
class RoleFieldPermissionSerializer(CustomModelSerializer):
|
||||
class Meta:
|
||||
model = FieldPermission
|
||||
fields = "__all__"
|
||||
fields = ['id', 'menu', 'name', 'isCheck', 'data_range', 'role_menu_btn_perm_id', 'dept']
|
||||
|
||||
|
||||
class RoleMenuFieldSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色-菜单-字段 序列化
|
||||
"""
|
||||
is_query = serializers.SerializerMethodField()
|
||||
is_create = serializers.SerializerMethodField()
|
||||
is_update = serializers.SerializerMethodField()
|
||||
|
||||
def get_is_query(self, instance):
|
||||
params = self.request.query_params
|
||||
queryset = instance.menu_field.filter(role=params.get('role')).first()
|
||||
queryset = instance.menu_field.filter(role=params.get('roleId')).first()
|
||||
if queryset:
|
||||
return queryset.is_query
|
||||
return False
|
||||
|
||||
def get_is_create(self, instance):
|
||||
params = self.request.query_params
|
||||
queryset = instance.menu_field.filter(role=params.get('role')).first()
|
||||
queryset = instance.menu_field.filter(role=params.get('roleId')).first()
|
||||
if queryset:
|
||||
return queryset.is_create
|
||||
return False
|
||||
|
||||
def get_is_update(self, instance):
|
||||
params = self.request.query_params
|
||||
queryset = instance.menu_field.filter(role=params.get('role')).first()
|
||||
queryset = instance.menu_field.filter(role=params.get('roleId')).first()
|
||||
if queryset:
|
||||
return queryset.is_update
|
||||
return False
|
||||
@@ -111,54 +143,6 @@ class RoleMenuFieldSerializer(CustomModelSerializer):
|
||||
fields = ['id', 'field_name', 'title', 'is_query', 'is_create', 'is_update']
|
||||
|
||||
|
||||
class RoleMenuSerializer(CustomModelSerializer):
|
||||
menus = serializers.SerializerMethodField()
|
||||
|
||||
def get_menus(self, instance):
|
||||
menu_list = Menu.objects.filter(parent=instance['id']).values('id', 'name')
|
||||
serializer = RoleMenuPermissionSerializer(menu_list, many=True, request=self.request)
|
||||
return serializer.data
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = ['id', 'name', 'menus']
|
||||
|
||||
|
||||
class RoleMenuPermissionSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单和按钮权限
|
||||
"""
|
||||
# name = serializers.SerializerMethodField()
|
||||
isCheck = serializers.SerializerMethodField()
|
||||
btns = serializers.SerializerMethodField()
|
||||
columns = serializers.SerializerMethodField()
|
||||
|
||||
# def get_name(self, instance):
|
||||
# parent_list = Menu.get_all_parent(instance['id'])
|
||||
# names = [d["name"] for d in parent_list]
|
||||
# return "/".join(names)
|
||||
def get_isCheck(self, instance):
|
||||
params = self.request.query_params
|
||||
return RoleMenuPermission.objects.filter(
|
||||
menu__id=instance['id'],
|
||||
role__id=params.get('role'),
|
||||
).exists()
|
||||
|
||||
def get_btns(self, instance):
|
||||
btn_list = MenuButton.objects.filter(menu__id=instance['id']).values('id', 'name', 'value')
|
||||
serializer = RoleButtonPermissionSerializer(btn_list, many=True, request=self.request)
|
||||
return serializer.data
|
||||
|
||||
def get_columns(self, instance):
|
||||
col_list = MenuField.objects.filter(menu=instance['id'])
|
||||
serializer = RoleMenuFieldSerializer(col_list, many=True, request=self.request)
|
||||
return serializer.data
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = ['id', 'name', 'isCheck', 'btns', 'columns']
|
||||
|
||||
|
||||
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
||||
"""
|
||||
菜单按钮接口
|
||||
@@ -174,202 +158,111 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
||||
update_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
|
||||
extra_filter_class = []
|
||||
|
||||
# @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
# def get_role_premission(self, request):
|
||||
# """
|
||||
# 角色授权获取:
|
||||
# :param request: role
|
||||
# :return: menu,btns,columns
|
||||
# """
|
||||
# params = request.query_params
|
||||
# is_superuser = request.user.is_superuser
|
||||
# if is_superuser:
|
||||
# queryset = Menu.objects.filter(status=1, is_catalog=True).values('name', 'id').all()
|
||||
# else:
|
||||
# role_id = request.user.role.values_list('id', flat=True)
|
||||
# menu_list = RoleMenuPermission.objects.filter(role__in=role_id).values_list('menu__id', flat=True)
|
||||
# queryset = Menu.objects.filter(status=1, is_catalog=True, id__in=menu_list).values('name', 'id').all()
|
||||
# serializer = RoleMenuSerializer(queryset, many=True, request=request)
|
||||
# data = serializer.data
|
||||
# return DetailResponse(data=data)
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def get_role_menu(self, request):
|
||||
"""
|
||||
获取 角色-菜单
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
menu_queryset = Menu.objects.all()
|
||||
serializer = RoleMenuSerializer(menu_queryset, many=True, request=request)
|
||||
return DetailResponse(data=serializer.data)
|
||||
|
||||
@action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def set_role_menu(self, request):
|
||||
"""
|
||||
设置 角色-菜单
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
data = request.data
|
||||
roleId = data.get('roleId')
|
||||
menuId = data.get('menuId')
|
||||
isCheck = data.get('isCheck')
|
||||
if isCheck:
|
||||
# 添加权限:创建关联记录
|
||||
instance = RoleMenuPermission.objects.create(role_id=roleId, menu_id=menuId)
|
||||
else:
|
||||
# 删除权限:移除关联记录
|
||||
RoleMenuPermission.objects.filter(role_id=roleId, menu_id=menuId).delete()
|
||||
menu_instance = Menu.objects.get(id=menuId)
|
||||
serializer = RoleMenuSerializer(menu_instance, request=request)
|
||||
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def get_role_permission(self, request):
|
||||
def get_role_menu_btn_field(self, request):
|
||||
"""
|
||||
获取 角色-菜单-按钮-列字段
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
params = request.query_params
|
||||
# 需要授权的角色信息
|
||||
current_role = params.get('role', None)
|
||||
# 当前登录用户的角色
|
||||
role_list = request.user.role.values_list('id', flat=True)
|
||||
if current_role is None:
|
||||
return ErrorResponse(msg='参数错误')
|
||||
is_superuser = request.user.is_superuser
|
||||
if is_superuser:
|
||||
menu_queryset = Menu.objects.prefetch_related('menuPermission').prefetch_related(
|
||||
'menufield_set')
|
||||
else:
|
||||
role_id_list = request.user.role.values_list('id', flat=True)
|
||||
menu_list = RoleMenuPermission.objects.filter(role__in=role_id_list).values_list('menu__id', flat=True)
|
||||
|
||||
# 当前角色已授权的菜单
|
||||
menu_queryset = Menu.objects.filter(id__in=menu_list).prefetch_related('menuPermission').prefetch_related(
|
||||
'menufield_set')
|
||||
result = []
|
||||
for menu_item in menu_queryset:
|
||||
isCheck = RoleMenuPermission.objects.filter(
|
||||
menu_id=menu_item.id,
|
||||
role_id=current_role
|
||||
).exists()
|
||||
dicts = {
|
||||
'name': menu_item.name,
|
||||
'id': menu_item.id,
|
||||
'parent': menu_item.parent.id if menu_item.parent else None,
|
||||
'isCheck': isCheck,
|
||||
'btns': [],
|
||||
'columns': []
|
||||
}
|
||||
for mb_item in menu_item.menuPermission.all():
|
||||
rolemenubuttonpermission_queryset = RoleMenuButtonPermission.objects.filter(
|
||||
menu_button_id=mb_item.id,
|
||||
role_id=current_role
|
||||
).first()
|
||||
dicts['btns'].append(
|
||||
{
|
||||
'id': mb_item.id,
|
||||
'name': mb_item.name,
|
||||
'value': mb_item.value,
|
||||
'data_range': rolemenubuttonpermission_queryset.data_range
|
||||
if rolemenubuttonpermission_queryset
|
||||
else None,
|
||||
'isCheck': bool(rolemenubuttonpermission_queryset),
|
||||
'dept': rolemenubuttonpermission_queryset.dept.all().values_list('id', flat=True)
|
||||
if rolemenubuttonpermission_queryset
|
||||
else [],
|
||||
}
|
||||
)
|
||||
for column_item in menu_item.menufield_set.all():
|
||||
# 需要授权角色已拥有的列权限
|
||||
fieldpermission_queryset = column_item.menu_field.filter(role_id=current_role).first()
|
||||
is_query = fieldpermission_queryset.is_query if fieldpermission_queryset else False
|
||||
is_create = fieldpermission_queryset.is_create if fieldpermission_queryset else False
|
||||
is_update = fieldpermission_queryset.is_update if fieldpermission_queryset else False
|
||||
# 当前登录用户角色可分配的列权限
|
||||
fieldpermission_queryset_disabled = column_item.menu_field.filter(role_id__in=role_list).first()
|
||||
disabled_query = fieldpermission_queryset_disabled.is_query if fieldpermission_queryset_disabled else True
|
||||
disabled_create = fieldpermission_queryset_disabled.is_create if fieldpermission_queryset_disabled else True
|
||||
disabled_update = fieldpermission_queryset_disabled.is_update if fieldpermission_queryset_disabled else True
|
||||
|
||||
dicts['columns'].append({
|
||||
'id': column_item.id,
|
||||
'field_name': column_item.field_name,
|
||||
'title': column_item.title,
|
||||
'is_query': is_query,
|
||||
'is_create': is_create,
|
||||
'is_update': is_update,
|
||||
'disabled_query': False if is_superuser else not disabled_query,
|
||||
'disabled_create': False if is_superuser else not disabled_create,
|
||||
'disabled_update': False if is_superuser else not disabled_update,
|
||||
})
|
||||
result.append(dicts)
|
||||
return DetailResponse(data=result)
|
||||
menuId = params.get('menuId', None)
|
||||
menu_btn_queryset = MenuButton.objects.filter(menu_id=menuId)
|
||||
menu_btn_serializer = RoleMenuButtonSerializer(menu_btn_queryset, many=True, request=request)
|
||||
menu_field_queryset = MenuField.objects.filter(menu_id=menuId)
|
||||
menu_field_serializer = RoleMenuFieldSerializer(menu_field_queryset, many=True, request=request)
|
||||
return DetailResponse(data={'menu_btn': menu_btn_serializer.data, 'menu_field': menu_field_serializer.data})
|
||||
|
||||
@action(methods=['PUT'], detail=True, permission_classes=[IsAuthenticated])
|
||||
def set_role_premission(self, request, pk):
|
||||
def set_role_menu_field(self, request, pk):
|
||||
"""
|
||||
对角色的菜单和按钮及按钮范围授权:
|
||||
:param request:
|
||||
:param pk: role
|
||||
:return:
|
||||
设置 角色-菜单-列字段
|
||||
"""
|
||||
body = request.data
|
||||
RoleMenuPermission.objects.filter(role=pk).delete()
|
||||
RoleMenuButtonPermission.objects.filter(role=pk).delete()
|
||||
for item in body:
|
||||
if item.get('isCheck'):
|
||||
RoleMenuPermission.objects.create(role_id=pk, menu_id=item["id"])
|
||||
for btn in item.get('btns'):
|
||||
if btn.get('isCheck'):
|
||||
data_range = btn.get('data_range', 0) or 0
|
||||
instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),
|
||||
data_range=data_range)
|
||||
instance.dept.set(btn.get('dept', []))
|
||||
for col in item.get('columns'):
|
||||
FieldPermission.objects.update_or_create(role_id=pk, field_id=col.get('id'),
|
||||
defaults={
|
||||
'is_query': col.get('is_query'),
|
||||
'is_create': col.get('is_create'),
|
||||
'is_update': col.get('is_update')
|
||||
})
|
||||
return DetailResponse(msg="授权成功")
|
||||
data = request.data
|
||||
for col in data:
|
||||
FieldPermission.objects.update_or_create(
|
||||
role_id=pk, field_id=col.get('id'),
|
||||
defaults={
|
||||
'is_create': col.get('is_create'),
|
||||
'is_update': col.get('is_update'),
|
||||
'is_query': col.get('is_query'),
|
||||
})
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def role_menu_get_button(self, request):
|
||||
"""
|
||||
当前用户角色和菜单获取可下拉选项的按钮:角色授权页面使用
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
if params := request.query_params:
|
||||
if menu_id := params.get('menu', None):
|
||||
is_superuser = request.user.is_superuser
|
||||
if is_superuser:
|
||||
queryset = MenuButton.objects.filter(menu=menu_id).values('id', 'name')
|
||||
else:
|
||||
role_list = request.user.role.values_list('id', flat=True)
|
||||
queryset = RoleMenuButtonPermission.objects.filter(
|
||||
role__in=role_list, menu_button__menu=menu_id
|
||||
).values(btn_id=F('menu_button__id'), name=F('menu_button__name'))
|
||||
return DetailResponse(data=queryset)
|
||||
return ErrorResponse(msg="参数错误")
|
||||
return DetailResponse(data=[], msg="更新成功")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def data_scope(self, request):
|
||||
@action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def set_role_menu_btn(self, request):
|
||||
"""
|
||||
获取数据权限范围:角色授权页面使用
|
||||
:param request:
|
||||
:return:
|
||||
设置 角色-菜单-按钮
|
||||
"""
|
||||
is_superuser = request.user.is_superuser
|
||||
if is_superuser:
|
||||
data = [
|
||||
{"value": 0, "label": '仅本人数据权限'},
|
||||
{"value": 1, "label": '本部门及以下数据权限'},
|
||||
{"value": 2, "label": '本部门数据权限'},
|
||||
{"value": 3, "label": '全部数据权限'},
|
||||
{"value": 4, "label": '自定义数据权限'}
|
||||
]
|
||||
return DetailResponse(data=data)
|
||||
data = request.data
|
||||
isCheck = data.get('isCheck', None)
|
||||
roleId = data.get('roleId', None)
|
||||
btnId = data.get('btnId', None)
|
||||
data_range = data.get('data_range', None) or 0 # 默认仅本人权限
|
||||
dept = data.get('dept', None) or [] # 默认空部门
|
||||
|
||||
if isCheck:
|
||||
# 添加权限:创建关联记录
|
||||
instance = RoleMenuButtonPermission.objects.create(role_id=roleId,
|
||||
menu_button_id=btnId,
|
||||
data_range=data_range)
|
||||
# 自定义部门权限
|
||||
if data_range == 4 and dept:
|
||||
instance.dept.set(dept)
|
||||
else:
|
||||
params = request.query_params
|
||||
data = [{"value": 0, "label": '仅本人数据权限'}]
|
||||
role_list = request.user.role.values_list('id', flat=True)
|
||||
# 权限页面进入初始化获取所有的数据权限范围
|
||||
role_queryset = RoleMenuButtonPermission.objects.filter(
|
||||
role__in=role_list
|
||||
).values_list('data_range', flat=True)
|
||||
# 通过按钮小齿轮获取指定按钮的权限
|
||||
if menu_button_id := params.get('menu_button', None):
|
||||
role_queryset = RoleMenuButtonPermission.objects.filter(
|
||||
role__in=role_list, menu_button__id=menu_button_id
|
||||
).values_list('data_range', flat=True)
|
||||
# 删除权限:移除关联记录
|
||||
RoleMenuButtonPermission.objects.filter(role_id=roleId, menu_button_id=btnId).delete()
|
||||
menu_btn_instance = MenuButton.objects.get(id=btnId)
|
||||
serializer = RoleMenuButtonSerializer(menu_btn_instance, request=request)
|
||||
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||
|
||||
data_range_list = list(set(role_queryset))
|
||||
for item in data_range_list:
|
||||
if item == 0:
|
||||
data = data
|
||||
elif item == 1:
|
||||
data.extend([
|
||||
{"value": 1, "label": '本部门及以下数据权限'},
|
||||
{"value": 2, "label": '本部门数据权限'}
|
||||
])
|
||||
elif item == 2:
|
||||
data.extend([{"value": 2, "label": '本部门数据权限'}])
|
||||
elif item == 3:
|
||||
data.extend([{"value": 3, "label": '全部数据权限'}])
|
||||
elif item == 4:
|
||||
data.extend([{"value": 4, "label": '自定义数据权限'}])
|
||||
else:
|
||||
data = []
|
||||
return DetailResponse(data=data)
|
||||
@action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def set_role_menu_btn_data_range(self, request):
|
||||
"""
|
||||
设置 角色-菜单-按钮-权限
|
||||
"""
|
||||
data = request.data
|
||||
instance = RoleMenuButtonPermission.objects.get(id=data.get('role_menu_btn_perm_id'))
|
||||
instance.data_range = data.get('data_range')
|
||||
instance.dept.add(*data.get('dept'))
|
||||
if not data.get('dept'):
|
||||
instance.dept.clear()
|
||||
instance.save()
|
||||
serializer = RoleMenuButtonPermissionSerializer(instance, request=request)
|
||||
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||
|
||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def role_to_dept_all(self, request):
|
||||
@@ -395,55 +288,3 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
||||
dept["disabled"] = False if is_superuser else dept["id"] not in dept_checked_disabled
|
||||
data.append(dept)
|
||||
return DetailResponse(data=data)
|
||||
|
||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def menu_to_button(self, request):
|
||||
"""
|
||||
根据所选择菜单获取已配置的按钮/接口权限:角色授权页面使用
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
params = request.query_params
|
||||
menu_id = params.get('menu', None)
|
||||
if menu_id is None:
|
||||
return ErrorResponse(msg="未获取到参数")
|
||||
is_superuser = request.user.is_superuser
|
||||
if is_superuser:
|
||||
queryset = RoleMenuButtonPermission.objects.filter(menu_button__menu=menu_id).values(
|
||||
'id',
|
||||
'data_range',
|
||||
'menu_button',
|
||||
'menu_button__name',
|
||||
'menu_button__value'
|
||||
)
|
||||
return DetailResponse(data=queryset)
|
||||
else:
|
||||
if params:
|
||||
|
||||
role_id = params.get('role', None)
|
||||
if role_id is None:
|
||||
return ErrorResponse(msg="未获取到参数")
|
||||
queryset = RoleMenuButtonPermission.objects.filter(role=role_id, menu_button__menu=menu_id).values(
|
||||
'id',
|
||||
'data_range',
|
||||
'menu_button',
|
||||
'menu_button__name',
|
||||
'menu_button__value'
|
||||
)
|
||||
return DetailResponse(data=queryset)
|
||||
return ErrorResponse(msg="未获取到参数")
|
||||
|
||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def role_to_menu(self, request):
|
||||
"""
|
||||
获取角色对应的按钮权限
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
params = request.query_params
|
||||
role_id = params.get('role', None)
|
||||
if role_id is None:
|
||||
return ErrorResponse(msg="未获取到参数")
|
||||
queryset = RoleMenuPermission.objects.filter(role_id=role_id).values_list('menu_id', flat=True).distinct()
|
||||
|
||||
return DetailResponse(data=queryset)
|
||||
|
||||
@@ -286,6 +286,7 @@ class UserViewSet(CustomModelViewSet):
|
||||
"dept": user.dept_id,
|
||||
"is_superuser": user.is_superuser,
|
||||
"role": user.role.values_list('id', flat=True),
|
||||
"pwd_change_count":user.pwd_change_count
|
||||
}
|
||||
if hasattr(connection, 'tenant'):
|
||||
result['tenant_id'] = connection.tenant and connection.tenant.id
|
||||
@@ -319,7 +320,6 @@ class UserViewSet(CustomModelViewSet):
|
||||
"""密码修改"""
|
||||
data = request.data
|
||||
old_pwd = data.get("oldPassword")
|
||||
print(old_pwd)
|
||||
new_pwd = data.get("newPassword")
|
||||
new_pwd2 = data.get("newPassword2")
|
||||
if old_pwd is None or new_pwd is None or new_pwd2 is None:
|
||||
@@ -330,13 +330,33 @@ class UserViewSet(CustomModelViewSet):
|
||||
if not verify_password:
|
||||
old_pwd_md5 = hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest()
|
||||
verify_password = check_password(str(old_pwd_md5), request.user.password)
|
||||
# 创建用户时、自定义密码无法修改问题
|
||||
if not verify_password:
|
||||
old_pwd_md5 = hashlib.md5(old_pwd_md5.encode(encoding='UTF-8')).hexdigest()
|
||||
verify_password = check_password(str(old_pwd_md5), request.user.password)
|
||||
if verify_password:
|
||||
# request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest())
|
||||
request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest())
|
||||
request.user.pwd_change_count += 1
|
||||
request.user.save()
|
||||
return DetailResponse(data=None, msg="修改成功")
|
||||
else:
|
||||
return ErrorResponse(msg="旧密码不正确")
|
||||
|
||||
@action(methods=["post"], detail=False, permission_classes=[IsAuthenticated])
|
||||
def login_change_password(self, request, *args, **kwargs):
|
||||
"""初次登录进行密码修改"""
|
||||
data = request.data
|
||||
new_pwd = data.get("password")
|
||||
new_pwd2 = data.get("password_regain")
|
||||
if new_pwd != new_pwd2:
|
||||
return ErrorResponse(msg="两次密码不匹配")
|
||||
else:
|
||||
request.user.password = make_password(new_pwd)
|
||||
request.user.pwd_change_count += 1
|
||||
request.user.save()
|
||||
return DetailResponse(data=None, msg="修改成功")
|
||||
|
||||
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
|
||||
def reset_to_default_password(self, request,pk):
|
||||
"""恢复默认密码"""
|
||||
|
||||
Reference in New Issue
Block a user