init
This commit is contained in:
0
backend/dvadmin/system/__init__.py
Normal file
0
backend/dvadmin/system/__init__.py
Normal file
3
backend/dvadmin/system/admin.py
Normal file
3
backend/dvadmin/system/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
backend/dvadmin/system/apps.py
Normal file
6
backend/dvadmin/system/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class SystemConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'dvadmin.system'
|
||||
0
backend/dvadmin/system/fixtures/__init__.py
Normal file
0
backend/dvadmin/system/fixtures/__init__.py
Normal file
345
backend/dvadmin/system/fixtures/initSerializer.py
Normal file
345
backend/dvadmin/system/fixtures/initSerializer.py
Normal file
@@ -0,0 +1,345 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
import django
|
||||
django.setup()
|
||||
from dvadmin.system.models import Role, Dept, Users, Menu, MenuButton, ApiWhiteList, Dictionary, SystemConfig, \
|
||||
RoleMenuPermission, RoleMenuButtonPermission
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
|
||||
|
||||
class UsersInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
role_key = self.initial_data.get('role_key', [])
|
||||
role_ids = Role.objects.filter(key__in=role_key).values_list('id', flat=True)
|
||||
instance.role.set(role_ids)
|
||||
dept_key = self.initial_data.get('dept_key', None)
|
||||
dept_id = Dept.objects.filter(key=dept_key).first()
|
||||
instance.dept = dept_id
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
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']
|
||||
read_only_fields = ['id']
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class MenuButtonInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = MenuButton
|
||||
fields = ['id', 'name', 'value', 'api', 'method', 'menu']
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
||||
class MenuInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
递归深度获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
name = serializers.CharField(required=False)
|
||||
children = serializers.SerializerMethodField()
|
||||
menu_button = serializers.SerializerMethodField()
|
||||
|
||||
def get_children(self, obj: Menu):
|
||||
data = []
|
||||
instance = Menu.objects.filter(parent_id=obj.id)
|
||||
if instance:
|
||||
serializer = MenuInitSerializer(instance=instance, many=True)
|
||||
data = serializer.data
|
||||
return data
|
||||
|
||||
def get_menu_button(self, obj: Menu):
|
||||
data = []
|
||||
instance = obj.menuPermission.order_by('method')
|
||||
if instance:
|
||||
data = list(instance.values('name', 'value', 'api', 'method'))
|
||||
return data
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
children = self.initial_data.get('children')
|
||||
menu_button = self.initial_data.get('menu_button')
|
||||
# 菜单表
|
||||
if children:
|
||||
for menu_data in children:
|
||||
menu_data['parent'] = instance.id
|
||||
filter_data = {
|
||||
"name": menu_data['name'],
|
||||
"web_path": menu_data['web_path'],
|
||||
"component": menu_data['component'],
|
||||
"component_name": menu_data['component_name'],
|
||||
}
|
||||
instance_obj = Menu.objects.filter(**filter_data).first()
|
||||
if instance_obj and not self.initial_data.get('reset'):
|
||||
continue
|
||||
serializer = MenuInitSerializer(instance_obj, data=menu_data, request=self.request)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
# 菜单按钮
|
||||
if menu_button:
|
||||
for menu_button_data in menu_button:
|
||||
menu_button_data['menu'] = instance.id
|
||||
filter_data = {
|
||||
"menu": menu_button_data['menu'],
|
||||
"value": menu_button_data['value']
|
||||
}
|
||||
instance_obj = MenuButton.objects.filter(**filter_data).first()
|
||||
serializer = MenuButtonInitSerializer(instance_obj, data=menu_button_data, request=self.request)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = ['name', 'icon', 'sort', 'is_link', 'is_catalog', 'web_path', 'component', 'component_name', 'status',
|
||||
'cache', 'visible', 'parent', 'children', 'menu_button', 'creator', 'dept_belong_id']
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
read_only_fields = ['id', 'children']
|
||||
|
||||
|
||||
class RoleInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = ['name', 'key', 'sort', 'status', 'admin',
|
||||
'creator', 'dept_belong_id']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class RoleMenuInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化角色菜单(用于生成初始化json文件)
|
||||
"""
|
||||
role_key = serializers.CharField(max_length=100,required=True)
|
||||
menu_component_name = serializers.CharField(max_length=100,required=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
init_data = self.initial_data
|
||||
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(component_name=init_data['menu_component_name']).first()
|
||||
validated_data['role'] = role_id
|
||||
validated_data['menu'] = menu_id
|
||||
return super().create(validated_data)
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuPermission
|
||||
fields = ['role_key','menu_component_name','creator', 'dept_belong_id']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'role': {'required': False},
|
||||
'menu': {'required': False},
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class RoleMenuButtonInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化角色菜单按钮(用于生成初始化json文件)
|
||||
"""
|
||||
role_key = serializers.CharField(max_length=100,required=True)
|
||||
menu_button_value = serializers.CharField(max_length=100,required=True)
|
||||
data_range = serializers.CharField(max_length=100, required=False)
|
||||
|
||||
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
|
||||
validated_data['menu_button'] = menu_button_id
|
||||
instance = super().create(validated_data)
|
||||
instance.dept.set([])
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuButtonPermission
|
||||
fields = ['role_key','menu_button_value','data_range','dept','creator', 'dept_belong_id']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'role': {'required': False},
|
||||
'menu': {'required': False},
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ApiWhiteListInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ApiWhiteList
|
||||
fields = ['url', 'method', 'enable_datasource', 'creator', 'dept_belong_id']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class DeptInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
递归深度获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
children = serializers.SerializerMethodField()
|
||||
|
||||
def get_children(self, obj: Dept):
|
||||
data = []
|
||||
instance = Dept.objects.filter(parent_id=obj.id)
|
||||
if instance:
|
||||
serializer = DeptInitSerializer(instance=instance, many=True)
|
||||
data = serializer.data
|
||||
return data
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
children = self.initial_data.get('children')
|
||||
if children:
|
||||
for menu_data in children:
|
||||
menu_data['parent'] = instance.id
|
||||
filter_data = {
|
||||
"name": menu_data['name'],
|
||||
"parent": menu_data['parent'],
|
||||
"key": menu_data['key']
|
||||
}
|
||||
instance_obj = Dept.objects.filter(**filter_data).first()
|
||||
if instance_obj and not self.initial_data.get('reset'):
|
||||
continue
|
||||
serializer = DeptInitSerializer(instance_obj, data=menu_data, request=self.request)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
fields = ['name', 'sort', 'owner', 'phone', 'email', 'status', 'parent', 'creator', 'dept_belong_id',
|
||||
'children', 'key']
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
read_only_fields = ['id', 'children']
|
||||
|
||||
|
||||
class DictionaryInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
children = serializers.SerializerMethodField()
|
||||
|
||||
def get_children(self, obj: Dictionary):
|
||||
data = []
|
||||
instance = Dictionary.objects.filter(parent_id=obj.id)
|
||||
if instance:
|
||||
serializer = DictionaryInitSerializer(instance=instance, many=True)
|
||||
data = serializer.data
|
||||
return data
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
children = self.initial_data.get('children')
|
||||
# 菜单表
|
||||
if children:
|
||||
for data in children:
|
||||
data['parent'] = instance.id
|
||||
filter_data = {
|
||||
"value": data['value'],
|
||||
"parent": data['parent']
|
||||
}
|
||||
instance_obj = Dictionary.objects.filter(**filter_data).first()
|
||||
if instance_obj and not self.initial_data.get('reset'):
|
||||
continue
|
||||
serializer = DictionaryInitSerializer(instance_obj, data=data, request=self.request)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = Dictionary
|
||||
fields = ['label', 'value', 'parent', 'type', 'color', 'is_value', 'status', 'sort', 'remark', 'creator',
|
||||
'dept_belong_id', 'children']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
|
||||
|
||||
class SystemConfigInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化获取数信息(用于生成初始化json文件)
|
||||
"""
|
||||
children = serializers.SerializerMethodField()
|
||||
|
||||
def get_children(self, obj: SystemConfig):
|
||||
data = []
|
||||
instance = SystemConfig.objects.filter(parent_id=obj.id)
|
||||
if instance:
|
||||
serializer = SystemConfigInitSerializer(instance=instance, many=True)
|
||||
data = serializer.data
|
||||
return data
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
children = self.initial_data.get('children')
|
||||
# 菜单表
|
||||
if children:
|
||||
for data in children:
|
||||
data['parent'] = instance.id
|
||||
filter_data = {
|
||||
"key": data['key'],
|
||||
"parent": data['parent']
|
||||
}
|
||||
instance_obj = SystemConfig.objects.filter(**filter_data).first()
|
||||
if instance_obj and not self.initial_data.get('reset'):
|
||||
continue
|
||||
serializer = SystemConfigInitSerializer(instance_obj, data=data, request=self.request)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = SystemConfig
|
||||
fields = ['parent', 'title', 'key', 'value', 'sort', 'status', 'data_options', 'form_item_type', 'rule',
|
||||
'placeholder', 'setting', 'creator', 'dept_belong_id', 'children']
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
'creator': {'write_only': True},
|
||||
'dept_belong_id': {'write_only': True}
|
||||
}
|
||||
7
backend/dvadmin/system/fixtures/init_apiwhitelist.json
Normal file
7
backend/dvadmin/system/fixtures/init_apiwhitelist.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"url": "/api/system/dept_lazy_tree/",
|
||||
"method": 0,
|
||||
"enable_datasource": true
|
||||
}
|
||||
]
|
||||
36
backend/dvadmin/system/fixtures/init_dept.json
Normal file
36
backend/dvadmin/system/fixtures/init_dept.json
Normal file
@@ -0,0 +1,36 @@
|
||||
[
|
||||
{
|
||||
"name": "DVAdmin团队",
|
||||
"key": "dvadmin",
|
||||
"sort": 1,
|
||||
"owner": "",
|
||||
"phone": "",
|
||||
"email": "",
|
||||
"status": true,
|
||||
"parent": null,
|
||||
"children": [
|
||||
{
|
||||
"name": "运营部",
|
||||
"key": "",
|
||||
"sort": 2,
|
||||
"owner": "",
|
||||
"phone": "",
|
||||
"email": "",
|
||||
"status": true,
|
||||
"parent": 1,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"name": "技术部",
|
||||
"key": "technology",
|
||||
"sort": 1,
|
||||
"owner": "",
|
||||
"phone": "",
|
||||
"email": "",
|
||||
"status": true,
|
||||
"parent": 3,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
550
backend/dvadmin/system/fixtures/init_dictionary.json
Normal file
550
backend/dvadmin/system/fixtures/init_dictionary.json
Normal file
@@ -0,0 +1,550 @@
|
||||
[
|
||||
{
|
||||
"label": "启用/禁用-布尔值",
|
||||
"value": "button_status_bool",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "启用",
|
||||
"value": "true",
|
||||
"parent": 1,
|
||||
"type": 6,
|
||||
"color": "success",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "禁用",
|
||||
"value": "false",
|
||||
"parent": 1,
|
||||
"type": 6,
|
||||
"color": "danger",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "系统按钮",
|
||||
"value": "system_button",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "新增",
|
||||
"value": "Create",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "success",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "编辑",
|
||||
"value": "Update",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "primary",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "删除",
|
||||
"value": "Delete",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "danger",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 3,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "详情",
|
||||
"value": "Retrieve",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "info",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 4,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "查询",
|
||||
"value": "Search",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "warning",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 5,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "保存",
|
||||
"value": "Save",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "success",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 6,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "导入",
|
||||
"value": "Import",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "primary",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 7,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "导出",
|
||||
"value": "Export",
|
||||
"parent": 4,
|
||||
"type": 0,
|
||||
"color": "warning",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 8,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "启用/禁用-数字值",
|
||||
"value": "button_status_number",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 3,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "启用",
|
||||
"value": "1",
|
||||
"parent": 13,
|
||||
"type": 1,
|
||||
"color": "success",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "禁用",
|
||||
"value": "0",
|
||||
"parent": 13,
|
||||
"type": 1,
|
||||
"color": "danger",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "是/否-布尔值",
|
||||
"value": "button_whether_bool",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 4,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "是",
|
||||
"value": "true",
|
||||
"parent": 16,
|
||||
"type": 6,
|
||||
"color": "success",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "否",
|
||||
"value": "false",
|
||||
"parent": 16,
|
||||
"type": 6,
|
||||
"color": "danger",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "是/否-数字值",
|
||||
"value": "button_whether_number",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 5,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "是",
|
||||
"value": "1",
|
||||
"parent": 19,
|
||||
"type": 1,
|
||||
"color": "success",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "否",
|
||||
"value": "2",
|
||||
"parent": 19,
|
||||
"type": 1,
|
||||
"color": "danger",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "用户类型",
|
||||
"value": "user_type",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 6,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "后台用户",
|
||||
"value": "0",
|
||||
"parent": 22,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "前台用户",
|
||||
"value": "1",
|
||||
"parent": 22,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "表单类型",
|
||||
"value": "config_form_type",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 7,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "text",
|
||||
"value": "0",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 0,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "textarea",
|
||||
"value": "3",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 0,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "number",
|
||||
"value": "10",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 0,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "datetime",
|
||||
"value": "1",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "date",
|
||||
"value": "2",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "time",
|
||||
"value": "15",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 3,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "select",
|
||||
"value": "4",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 4,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "checkbox",
|
||||
"value": "5",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 5,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "radio",
|
||||
"value": "6",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 6,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "switch",
|
||||
"value": "9",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 6,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "文件附件",
|
||||
"value": "8",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 7,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "图片(单张)",
|
||||
"value": "7",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 8,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "图片(多张)",
|
||||
"value": "12",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 9,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "数组",
|
||||
"value": "11",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 11,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "关联表",
|
||||
"value": "13",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 13,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "关联表(多选)",
|
||||
"value": "14",
|
||||
"parent": 25,
|
||||
"type": 1,
|
||||
"color": "",
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 14,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "性别",
|
||||
"value": "gender",
|
||||
"parent": null,
|
||||
"type": 0,
|
||||
"color": null,
|
||||
"is_value": false,
|
||||
"status": true,
|
||||
"sort": 8,
|
||||
"remark": null,
|
||||
"children": [
|
||||
{
|
||||
"label": "未知",
|
||||
"value": "0",
|
||||
"parent": 42,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 0,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "男",
|
||||
"value": "1",
|
||||
"parent": 42,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 1,
|
||||
"remark": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"label": "女",
|
||||
"value": "2",
|
||||
"parent": 42,
|
||||
"type": 1,
|
||||
"color": null,
|
||||
"is_value": true,
|
||||
"status": true,
|
||||
"sort": 2,
|
||||
"remark": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
646
backend/dvadmin/system/fixtures/init_menu.json
Normal file
646
backend/dvadmin/system/fixtures/init_menu.json
Normal file
@@ -0,0 +1,646 @@
|
||||
[
|
||||
{
|
||||
"name": "系统管理",
|
||||
"icon": "iconfont icon-xitongshezhi",
|
||||
"sort": 1,
|
||||
"is_link": false,
|
||||
"is_catalog": true,
|
||||
"web_path": "/system",
|
||||
"component": "",
|
||||
"component_name": "",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": null,
|
||||
"children": [
|
||||
{
|
||||
"name": "菜单管理",
|
||||
"icon": "iconfont icon-caidan",
|
||||
"sort": 1,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/menu",
|
||||
"component": "system/menu/index",
|
||||
"component_name": "menu",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "menu:Search",
|
||||
"api": "/api/system/menu/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "menu:Retrieve",
|
||||
"api": "/api/system/menu/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "menu:Create",
|
||||
"api": "/api/system/menu/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "menu:Update",
|
||||
"api": "/api/system/menu/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "menu:Delete",
|
||||
"api": "/api/system/menu/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "菜单按钮",
|
||||
"icon": "dot-circle-o",
|
||||
"sort": 2,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/menuButton",
|
||||
"component": "system/menuButton/index",
|
||||
"component_name": "menuButton",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": false,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "menu_button:Search",
|
||||
"api": "/api/system/menu_button/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "menu_button:Create",
|
||||
"api": "/api/system/menu_button/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "menu_button:Update",
|
||||
"api": "/api/system/menu_button/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "menu_button:Delete",
|
||||
"api": "/api/system/menu_button/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "部门管理",
|
||||
"icon": "ele-OfficeBuilding",
|
||||
"sort": 3,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/dept",
|
||||
"component": "system/dept/index",
|
||||
"component_name": "dept",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "dept:Search",
|
||||
"api": "/api/system/dept/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "dept:Retrieve",
|
||||
"api": "/api/system/dept/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "dept:Create",
|
||||
"api": "/api/system/dept/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "dept:Update",
|
||||
"api": "/api/system/dept/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "dept:Delete",
|
||||
"api": "/api/system/dept/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "角色管理",
|
||||
"icon": "ele-ColdDrink",
|
||||
"sort": 4,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/role",
|
||||
"component": "system/role/index",
|
||||
"component_name": "role",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "role:Search",
|
||||
"api": "/api/system/role/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "role:Retrieve",
|
||||
"api": "/api/system/role/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "role:Create",
|
||||
"api": "/api/system/role/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "role:Update",
|
||||
"api": "/api/system/role/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "保存",
|
||||
"value": "role:Save",
|
||||
"api": "/api/system/role/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "role:Delete",
|
||||
"api": "/api/system/role/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "用户管理",
|
||||
"icon": "iconfont icon-icon-",
|
||||
"sort": 6,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/user",
|
||||
"component": "system/user/index",
|
||||
"component_name": "user",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "user:Search",
|
||||
"api": "/api/system/user/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "user:Retrieve",
|
||||
"api": "/api/system/user/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "user:Create",
|
||||
"api": "/api/system/user/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "导出",
|
||||
"value": "user:Export",
|
||||
"api": "/api/system/user/export/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "导入",
|
||||
"value": "user:Import",
|
||||
"api": "/api/system/user/import/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "user:Update",
|
||||
"api": "/api/system/user/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "重设密码",
|
||||
"value": "user:ResetPassword",
|
||||
"api": "/api/system/user/{id}/reset_password/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "重置密码",
|
||||
"value": "user:DefaultPassword",
|
||||
"api": "/api/system/user/{id}/reset_to_default_password/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "user:Delete",
|
||||
"api": "/api/system/user/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "消息中心",
|
||||
"icon": "iconfont icon-xiaoxizhongxin",
|
||||
"sort": 7,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/messageCenter",
|
||||
"component": "system/messageCenter/index",
|
||||
"component_name": "messageCenter",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "messageCenter:Search",
|
||||
"api": "/api/system/message_center/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "messageCenter:Retrieve",
|
||||
"api": "/api/system/message_center/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "messageCenter:Create",
|
||||
"api": "/api/system/message_center/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "messageCenter:Update",
|
||||
"api": "/api/system/message_center/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "messageCenter:Delete",
|
||||
"api": "/api/system/menu/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "接口白名单",
|
||||
"icon": "ele-SetUp",
|
||||
"sort": 8,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/apiWhiteList",
|
||||
"component": "system/whiteList/index",
|
||||
"component_name": "whiteList",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 41,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "api_white_list:Search",
|
||||
"api": "/api/system/api_white_list/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "api_white_list:Retrieve",
|
||||
"api": "/api/system/api_white_list/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "api_white_list:Create",
|
||||
"api": "/api/system/api_white_list/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "api_white_list:Update",
|
||||
"api": "/api/system/api_white_list/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "api_white_list:Delete",
|
||||
"api": "/api/system/api_white_list/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"menu_button": []
|
||||
},
|
||||
{
|
||||
"name": "常规配置",
|
||||
"icon": "iconfont icon-configure",
|
||||
"sort": 2,
|
||||
"is_link": false,
|
||||
"is_catalog": true,
|
||||
"web_path": "/generalConfig",
|
||||
"component": "",
|
||||
"component_name": "",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": null,
|
||||
"children": [
|
||||
{
|
||||
"name": "系统配置",
|
||||
"icon": "iconfont icon-system",
|
||||
"sort": 0,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/config",
|
||||
"component": "system/config/index",
|
||||
"component_name": "config",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 49,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "system_config:Search",
|
||||
"api": "/api/system/system_config/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "system_config:Retrieve",
|
||||
"api": "/api/system/system_config/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "system_config:Create",
|
||||
"api": "/api/system/system_config/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "system_config:Update",
|
||||
"api": "/api/system/system_config/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "system_config:Delete",
|
||||
"api": "/api/system/system_config/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "字典管理",
|
||||
"icon": "iconfont icon-dict",
|
||||
"sort": 1,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/dictionary",
|
||||
"component": "system/dictionary/index",
|
||||
"component_name": "dictionary",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 49,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "dictionary:Search",
|
||||
"api": "/api/system/dictionary/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "dictionary:Retrieve",
|
||||
"api": "/api/system/dictionary/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "dictionary:Create",
|
||||
"api": "/api/system/dictionary/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "dictionary:Update",
|
||||
"api": "/api/system/dictionary/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "dictionary:Delete",
|
||||
"api": "/api/system/dictionary/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "地区管理",
|
||||
"icon": "iconfont icon-Area",
|
||||
"sort": 2,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/areas",
|
||||
"component": "system/areas/index",
|
||||
"component_name": "areas",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 49,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "area:Search",
|
||||
"api": "/api/system/area/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "area:Retrieve",
|
||||
"api": "/api/system/area/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "新增",
|
||||
"value": "area:Create",
|
||||
"api": "/api/system/area/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "area:Update",
|
||||
"api": "/api/system/area/{id}/",
|
||||
"method": 2
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "area:Delete",
|
||||
"api": "/api/system/area/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "附件管理",
|
||||
"icon": "iconfont icon-file",
|
||||
"sort": 3,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/file",
|
||||
"component": "system/fileList/index",
|
||||
"component_name": "file",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 49,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "file:Retrieve",
|
||||
"api": "/api/system/file/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "file:Search",
|
||||
"api": "/api/system/file/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "编辑",
|
||||
"value": "file:Update",
|
||||
"api": "/api/system/file/{id}/",
|
||||
"method": 1
|
||||
},
|
||||
{
|
||||
"name": "删除",
|
||||
"value": "file:Delete",
|
||||
"api": "/api/system/file/{id}/",
|
||||
"method": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"menu_button": []
|
||||
},
|
||||
{
|
||||
"name": "日志管理",
|
||||
"icon": "iconfont icon-rizhi",
|
||||
"sort": 3,
|
||||
"is_link": false,
|
||||
"is_catalog": true,
|
||||
"web_path": "/log",
|
||||
"component": "",
|
||||
"component_name": "",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": null,
|
||||
"children": [
|
||||
{
|
||||
"name": "登录日志",
|
||||
"icon": "iconfont icon-guanlidenglurizhi",
|
||||
"sort": 1,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/loginLog",
|
||||
"component": "system/log/loginLog/index",
|
||||
"component_name": "loginLog",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 54,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "login_log:Search",
|
||||
"api": "/api/system/login_log/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "login_log:Retrieve",
|
||||
"api": "/api/system/login_log/{id}/",
|
||||
"method": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "操作日志",
|
||||
"icon": "iconfont icon-caozuorizhi",
|
||||
"sort": 2,
|
||||
"is_link": false,
|
||||
"is_catalog": false,
|
||||
"web_path": "/operationLog",
|
||||
"component": "system/log/operationLog/index",
|
||||
"component_name": "operationLog",
|
||||
"status": true,
|
||||
"cache": false,
|
||||
"visible": true,
|
||||
"parent": 54,
|
||||
"children": [],
|
||||
"menu_button": [
|
||||
{
|
||||
"name": "详情",
|
||||
"value": "operation_log:Retrieve",
|
||||
"api": "/api/system/operation_log/{id}/",
|
||||
"method": 0
|
||||
},
|
||||
{
|
||||
"name": "查询",
|
||||
"value": "operation_log:Search",
|
||||
"api": "/api/system/operation_log/",
|
||||
"method": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"menu_button": []
|
||||
}
|
||||
]
|
||||
18
backend/dvadmin/system/fixtures/init_role.json
Normal file
18
backend/dvadmin/system/fixtures/init_role.json
Normal file
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"name": "管理员",
|
||||
"key": "admin",
|
||||
"sort": 1,
|
||||
"status": true,
|
||||
"admin": true,
|
||||
"remark": null
|
||||
},
|
||||
{
|
||||
"name": "用户",
|
||||
"key": "public",
|
||||
"sort": 2,
|
||||
"status": true,
|
||||
"admin": true,
|
||||
"remark": null
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"role_key": "admin",
|
||||
"menu_button_value": "menu:Search",
|
||||
"data_range": 0
|
||||
},
|
||||
{
|
||||
"role_key": "public",
|
||||
"menu_button_value":"menu:Search",
|
||||
"data_range": 0
|
||||
}
|
||||
]
|
||||
10
backend/dvadmin/system/fixtures/init_rolemenupermission.json
Normal file
10
backend/dvadmin/system/fixtures/init_rolemenupermission.json
Normal file
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"role_key": "admin",
|
||||
"menu_component_name": "menu"
|
||||
},
|
||||
{
|
||||
"role_key": "public",
|
||||
"menu_component_name": "menu"
|
||||
}
|
||||
]
|
||||
197
backend/dvadmin/system/fixtures/init_systemconfig.json
Normal file
197
backend/dvadmin/system/fixtures/init_systemconfig.json
Normal file
@@ -0,0 +1,197 @@
|
||||
[
|
||||
{
|
||||
"parent": null,
|
||||
"title": "基础配置",
|
||||
"key": "base",
|
||||
"value": null,
|
||||
"sort": 0,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": null,
|
||||
"placeholder": null,
|
||||
"setting": null,
|
||||
"children": [
|
||||
{
|
||||
"parent": 10,
|
||||
"title": "开启验证码",
|
||||
"key": "captcha_state",
|
||||
"value": true,
|
||||
"sort": 1,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 9,
|
||||
"rule": [
|
||||
{
|
||||
"message": "必填项不能为空",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"placeholder": "请选择",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 10,
|
||||
"title": "创建用户默认密码",
|
||||
"key": "default_password",
|
||||
"value": "admin123456",
|
||||
"sort": 2,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": [
|
||||
{
|
||||
"message": "必填项不能为空",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"placeholder": "请输入默认密码",
|
||||
"setting": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"parent": null,
|
||||
"title": "登录页配置",
|
||||
"key": "login",
|
||||
"value": null,
|
||||
"sort": 1,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": null,
|
||||
"placeholder": null,
|
||||
"setting": null,
|
||||
"children": [
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "网站名称",
|
||||
"key": "site_name",
|
||||
"value": "企业级后台管理系统",
|
||||
"sort": 1,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": [
|
||||
{
|
||||
"message": "必填项不能为空",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"placeholder": "请输入网站名称",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "登录网站logo",
|
||||
"key": "site_logo",
|
||||
"value": null,
|
||||
"sort": 2,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 7,
|
||||
"rule": [],
|
||||
"placeholder": "请上传网站logo",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "登录页背景图",
|
||||
"key": "login_background",
|
||||
"value": null,
|
||||
"sort": 3,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 7,
|
||||
"rule": [],
|
||||
"placeholder": "请上传登录背景页",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "版权信息",
|
||||
"key": "copyright",
|
||||
"value": "2021-2022 django-vue-admin.com 版权所有",
|
||||
"sort": 4,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": [
|
||||
{
|
||||
"message": "必填项不能为空",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"placeholder": "请输入版权信息",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "备案信息",
|
||||
"key": "keep_record",
|
||||
"value": "晋ICP备18005113号-3",
|
||||
"sort": 5,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": [
|
||||
{
|
||||
"message": "必填项不能为空",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"placeholder": "请输入备案信息",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "帮助链接",
|
||||
"key": "help_url",
|
||||
"value": "https://django-vue-admin.com",
|
||||
"sort": 6,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": "",
|
||||
"placeholder": "请输入帮助信息",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "隐私链接",
|
||||
"key": "privacy_url",
|
||||
"value": "#",
|
||||
"sort": 7,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": [],
|
||||
"placeholder": "请填写隐私链接",
|
||||
"setting": null,
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"parent": 1,
|
||||
"title": "条款链接",
|
||||
"key": "clause_url",
|
||||
"value": "#",
|
||||
"sort": 8,
|
||||
"status": true,
|
||||
"data_options": null,
|
||||
"form_item_type": 0,
|
||||
"rule": [],
|
||||
"placeholder": "请输入条款链接",
|
||||
"setting": null,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
59
backend/dvadmin/system/fixtures/init_users.json
Normal file
59
backend/dvadmin/system/fixtures/init_users.json
Normal file
@@ -0,0 +1,59 @@
|
||||
[
|
||||
{
|
||||
"username": "superadmin",
|
||||
"email": "dvadmin@django-vue-admin.com",
|
||||
"mobile": "13333333333",
|
||||
"avatar": null,
|
||||
"name": "超级管理员",
|
||||
"gender": 1,
|
||||
"user_type": 0,
|
||||
"role": [],
|
||||
"role_key": [
|
||||
"admin"
|
||||
],
|
||||
"dept_key": "dvadmin",
|
||||
"first_name": "",
|
||||
"last_name": "",
|
||||
"is_staff": true,
|
||||
"is_active": true,
|
||||
"password": "pbkdf2_sha256$260000$g17x5wlSiW1FZAh1Eudchw$ZeSAqj3Xak0io8v/pmPW0BX9EX5R2zFXDwbbD68oBFk=",
|
||||
"last_login": null,
|
||||
"is_superuser": true
|
||||
},
|
||||
{
|
||||
"username": "admin",
|
||||
"email": "dvadmin@django-vue-admin.com",
|
||||
"mobile": "18888888888",
|
||||
"avatar": "",
|
||||
"name": "管理员",
|
||||
"gender": 1,
|
||||
"user_type": 0,
|
||||
"role": [],
|
||||
"first_name": "",
|
||||
"last_name": "",
|
||||
"is_staff": true,
|
||||
"is_active": true,
|
||||
"password": "pbkdf2_sha256$260000$g17x5wlSiW1FZAh1Eudchw$ZeSAqj3Xak0io8v/pmPW0BX9EX5R2zFXDwbbD68oBFk=",
|
||||
"last_login": null,
|
||||
"is_superuser": false
|
||||
},
|
||||
{
|
||||
"username": "test",
|
||||
"email": "dvadmin@django-vue-admin.com",
|
||||
"mobile": "18888888888",
|
||||
"avatar": "",
|
||||
"name": "测试人员",
|
||||
"gender": 1,
|
||||
"user_type": 0,
|
||||
"role": [],
|
||||
"role_key": ["public"],
|
||||
"dept_key": "technology",
|
||||
"first_name": "",
|
||||
"last_name": "",
|
||||
"is_staff": true,
|
||||
"is_active": true,
|
||||
"password": "pbkdf2_sha256$260000$g17x5wlSiW1FZAh1Eudchw$ZeSAqj3Xak0io8v/pmPW0BX9EX5R2zFXDwbbD68oBFk=",
|
||||
"last_login": null,
|
||||
"is_superuser": false
|
||||
}
|
||||
]
|
||||
86
backend/dvadmin/system/fixtures/initialize.py
Normal file
86
backend/dvadmin/system/fixtures/initialize.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# 初始化
|
||||
import os
|
||||
|
||||
import django
|
||||
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
|
||||
django.setup()
|
||||
|
||||
from dvadmin.utils.core_initialize import CoreInitialize
|
||||
from dvadmin.system.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
|
||||
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
|
||||
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
|
||||
|
||||
|
||||
class Initialize(CoreInitialize):
|
||||
|
||||
def init_dept(self):
|
||||
"""
|
||||
初始化部门信息
|
||||
"""
|
||||
self.init_base(DeptInitSerializer, unique_fields=['name', 'parent','key'])
|
||||
|
||||
def init_role(self):
|
||||
"""
|
||||
初始化角色信息
|
||||
"""
|
||||
self.init_base(RoleInitSerializer, unique_fields=['key'])
|
||||
|
||||
def init_users(self):
|
||||
"""
|
||||
初始化用户信息
|
||||
"""
|
||||
self.init_base(UsersInitSerializer, unique_fields=['username'])
|
||||
|
||||
def init_menu(self):
|
||||
"""
|
||||
初始化菜单信息
|
||||
"""
|
||||
self.init_base(MenuInitSerializer, unique_fields=['name', 'web_path', 'component', 'component_name'])
|
||||
|
||||
def init_role_menu(self):
|
||||
"""
|
||||
初始化角色菜单信息
|
||||
"""
|
||||
self.init_base(RoleMenuInitSerializer, unique_fields=['role', 'menu'])
|
||||
|
||||
def init_role_menu_button(self):
|
||||
"""
|
||||
初始化角色菜单按钮信息
|
||||
"""
|
||||
self.init_base(RoleMenuButtonInitSerializer, unique_fields=['role', 'menu_button'])
|
||||
|
||||
|
||||
def init_api_white_list(self):
|
||||
"""
|
||||
初始API白名单
|
||||
"""
|
||||
self.init_base(ApiWhiteListInitSerializer, unique_fields=['url', 'method', ])
|
||||
|
||||
def init_dictionary(self):
|
||||
"""
|
||||
初始化字典表
|
||||
"""
|
||||
self.init_base(DictionaryInitSerializer, unique_fields=['value', 'parent', ])
|
||||
|
||||
def init_system_config(self):
|
||||
"""
|
||||
初始化系统配置表
|
||||
"""
|
||||
self.init_base(SystemConfigInitSerializer, unique_fields=['key', 'parent', ])
|
||||
|
||||
def run(self):
|
||||
self.init_dept()
|
||||
self.init_role()
|
||||
self.init_users()
|
||||
self.init_menu()
|
||||
self.init_role_menu()
|
||||
self.init_role_menu_button()
|
||||
self.init_api_white_list()
|
||||
self.init_dictionary()
|
||||
self.init_system_config()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Initialize(app='dvadmin.system').run()
|
||||
0
backend/dvadmin/system/management/__init__.py
Normal file
0
backend/dvadmin/system/management/__init__.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
import django
|
||||
from django.db.models import QuerySet
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
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.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
|
||||
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
|
||||
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
生产初始化菜单: python3 manage.py generate_init_json 生成初始化的model名
|
||||
例如:
|
||||
全部生成:python3 manage.py generate_init_json
|
||||
只生成某个model的: python3 manage.py generate_init_json users
|
||||
"""
|
||||
|
||||
def serializer_data(self, serializer, query_set: QuerySet):
|
||||
serializer = serializer(query_set, many=True)
|
||||
data = json.loads(json.dumps(serializer.data, ensure_ascii=False))
|
||||
with open(os.path.join(BASE_DIR, f'init_{query_set.model._meta.model_name}.json'), 'w') as f:
|
||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||
return
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("generate_name", nargs="*", type=str, help="初始化生成的表名")
|
||||
|
||||
def generate_users(self):
|
||||
self.serializer_data(UsersInitSerializer, Users.objects.all())
|
||||
|
||||
def generate_role(self):
|
||||
self.serializer_data(RoleInitSerializer, Role.objects.all())
|
||||
|
||||
def generate_dept(self):
|
||||
self.serializer_data(DeptInitSerializer, Dept.objects.filter(parent_id__isnull=True))
|
||||
|
||||
def generate_menu(self):
|
||||
self.serializer_data(MenuInitSerializer, Menu.objects.filter(parent_id__isnull=True))
|
||||
|
||||
def generate_api_white_list(self):
|
||||
self.serializer_data(ApiWhiteListInitSerializer, ApiWhiteList.objects.all())
|
||||
|
||||
def generate_dictionary(self):
|
||||
self.serializer_data(DictionaryInitSerializer, Dictionary.objects.filter(parent_id__isnull=True))
|
||||
|
||||
def generate_system_config(self):
|
||||
self.serializer_data(SystemConfigInitSerializer, SystemConfig.objects.filter(parent_id__isnull=True))
|
||||
|
||||
def handle(self, *args, **options):
|
||||
generate_name = options.get('generate_name')
|
||||
generate_name_dict = {
|
||||
"users": self.generate_users,
|
||||
"role": self.generate_role,
|
||||
"dept": self.generate_dept,
|
||||
"menu": self.generate_menu,
|
||||
"api_white_list": self.generate_api_white_list,
|
||||
"dictionary": self.generate_dictionary,
|
||||
"system_config": self.generate_system_config,
|
||||
}
|
||||
if not generate_name:
|
||||
for ele in generate_name_dict.keys():
|
||||
generate_name_dict[ele]()
|
||||
return
|
||||
|
||||
for generate_name in generate_name:
|
||||
if generate_name not in generate_name_dict:
|
||||
print(f"该初始化方法尚未配置\n{generate_name_dict}")
|
||||
raise Exception(f"该初始化方法尚未配置,已配置项:{list(generate_name_dict.keys())}")
|
||||
generate_name_dict[generate_name]()
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# with open(os.path.join(BASE_DIR, 'temp_init_menu.json')) as f:
|
||||
# for menu_data in json.load(f):
|
||||
# menu_data['creator'] = 1
|
||||
# menu_data['modifier'] = 1
|
||||
# menu_data['dept_belong_id'] = 1
|
||||
# request.user = Users.objects.order_by('create_datetime').first()
|
||||
# serializer = MenuInitSerializer(data=menu_data, request=request)
|
||||
# serializer.is_valid(raise_exception=True)
|
||||
# serializer.save()
|
||||
a = Users.objects.filter()
|
||||
print(type(Users.objects.filter()))
|
||||
53
backend/dvadmin/system/management/commands/init.py
Normal file
53
backend/dvadmin/system/management/commands/init.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import logging
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from application import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
项目初始化命令: python manage.py init
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
"init_name",
|
||||
nargs="*",
|
||||
type=str,
|
||||
)
|
||||
parser.add_argument("-y", nargs="*")
|
||||
parser.add_argument("-Y", nargs="*")
|
||||
parser.add_argument("-n", nargs="*")
|
||||
parser.add_argument("-N", nargs="*")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
reset = False
|
||||
if isinstance(options.get("y"), list) or isinstance(options.get("Y"), list):
|
||||
reset = True
|
||||
if isinstance(options.get("n"), list) or isinstance(options.get("N"), list):
|
||||
reset = False
|
||||
|
||||
for app in settings.INSTALLED_APPS:
|
||||
|
||||
try:
|
||||
exec(
|
||||
f"""
|
||||
from {app}.fixtures.initialize import Initialize
|
||||
Initialize(reset={reset},app="{app}").run()
|
||||
"""
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
# 兼容之前版本初始化
|
||||
try:
|
||||
exec(
|
||||
f"""
|
||||
from {app}.initialize import main
|
||||
main(reset={reset})
|
||||
"""
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
print("初始化数据完成!")
|
||||
83
backend/dvadmin/system/management/commands/init_area.py
Normal file
83
backend/dvadmin/system/management/commands/init_area.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# 城市联动
|
||||
"""
|
||||
到乡级 使用方法
|
||||
1. https://www.npmjs.com/package/china-division 下载数据,把对应的json放入对应目录
|
||||
2. 修改此文件中对应json名
|
||||
3. 右击执行此py文件进行初始化
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
|
||||
import django
|
||||
import pypinyin
|
||||
from django.core.management import BaseCommand
|
||||
from django.db import connection
|
||||
|
||||
from application import dispatch
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
|
||||
django.setup()
|
||||
from application.settings import BASE_DIR
|
||||
from dvadmin.system.models import Area
|
||||
|
||||
area_code_list = []
|
||||
|
||||
|
||||
def area_list(code_list, pcode=None, depth=1):
|
||||
"""
|
||||
递归获取所有列表
|
||||
"""
|
||||
for code_dict in code_list:
|
||||
code = code_dict.get('code', None)
|
||||
name = code_dict.get('name', None)
|
||||
children = code_dict.get('children', None)
|
||||
pinyin = ''.join([''.join(i) for i in pypinyin.pinyin(name, style=pypinyin.NORMAL)])
|
||||
area_code_list.append(
|
||||
{
|
||||
"name": name,
|
||||
"code": code,
|
||||
"level": depth,
|
||||
"pinyin": pinyin,
|
||||
"initials": pinyin[0].upper() if pinyin else "#",
|
||||
"pcode_id": pcode,
|
||||
}
|
||||
)
|
||||
if children:
|
||||
area_list(code_list=children, pcode=code, depth=depth + 1)
|
||||
|
||||
|
||||
def main():
|
||||
with open(os.path.join(BASE_DIR, 'dvadmin', 'system', 'util', 'pca-code.json'), 'r', encoding="utf-8") as load_f:
|
||||
code_list = json.load(load_f)
|
||||
area_list(code_list)
|
||||
if Area.objects.count() == 0:
|
||||
Area.objects.bulk_create([Area(**ele) for ele in area_code_list])
|
||||
else:
|
||||
for ele in area_code_list:
|
||||
code = ele.pop("code")
|
||||
Area.objects.update_or_create(code=code, defaults=ele)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
项目初始化命令: python manage.py init
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
pass
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
||||
print(f"正在准备初始化省份数据...")
|
||||
|
||||
if dispatch.is_tenants_mode():
|
||||
from django_tenants.utils import get_tenant_model
|
||||
from django_tenants.utils import tenant_context
|
||||
for tenant in get_tenant_model().objects.exclude(schema_name='public'):
|
||||
with tenant_context(tenant):
|
||||
print(f"租户[{connection.tenant.schema_name}]初始化数据开始...")
|
||||
main()
|
||||
print(f"租户[{connection.tenant.schema_name}]初始化数据完成!")
|
||||
else:
|
||||
main()
|
||||
print("省份数据初始化数据完成!")
|
||||
0
backend/dvadmin/system/migrations/__init__.py
Normal file
0
backend/dvadmin/system/migrations/__init__.py
Normal file
556
backend/dvadmin/system/models.py
Normal file
556
backend/dvadmin/system/models.py
Normal file
@@ -0,0 +1,556 @@
|
||||
import hashlib
|
||||
import os
|
||||
|
||||
from django.contrib.auth.models import AbstractUser, UserManager
|
||||
from django.db import models
|
||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||
from application import dispatch
|
||||
from dvadmin.utils.models import CoreModel, table_prefix
|
||||
|
||||
STATUS_CHOICES = (
|
||||
(0, "禁用"),
|
||||
(1, "启用"),
|
||||
)
|
||||
|
||||
|
||||
class Role(CoreModel):
|
||||
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="角色顺序")
|
||||
status = models.BooleanField(default=True, verbose_name="角色状态", help_text="角色状态")
|
||||
admin = models.BooleanField(default=False, verbose_name="是否为admin", help_text="是否为admin")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_role"
|
||||
verbose_name = "角色表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("sort",)
|
||||
|
||||
|
||||
class CustomUserManager(UserManager):
|
||||
|
||||
def create_superuser(self, username, email=None, password=None, **extra_fields):
|
||||
user = super(CustomUserManager, self).create_superuser(username, email, password, **extra_fields)
|
||||
user.set_password(password)
|
||||
try:
|
||||
user.role.add(Role.objects.get(name="管理员"))
|
||||
user.save(using=self._db)
|
||||
return user
|
||||
except ObjectDoesNotExist:
|
||||
user.delete()
|
||||
raise ValidationError("角色`管理员`不存在, 创建失败, 请先执行python manage.py init")
|
||||
|
||||
|
||||
class Users(CoreModel, AbstractUser):
|
||||
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号",
|
||||
help_text="用户账号")
|
||||
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
|
||||
mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")
|
||||
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
|
||||
name = models.CharField(max_length=40, verbose_name="姓名", help_text="姓名")
|
||||
GENDER_CHOICES = (
|
||||
(0, "未知"),
|
||||
(1, "男"),
|
||||
(2, "女"),
|
||||
)
|
||||
gender = models.IntegerField(
|
||||
choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True, help_text="性别"
|
||||
)
|
||||
USER_TYPE = (
|
||||
(0, "后台用户"),
|
||||
(1, "前台用户"),
|
||||
)
|
||||
user_type = models.IntegerField(
|
||||
choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型"
|
||||
)
|
||||
post = models.ManyToManyField(to="Post", blank=True, verbose_name="关联岗位", db_constraint=False,
|
||||
help_text="关联岗位")
|
||||
role = models.ManyToManyField(to="Role", blank=True, verbose_name="关联角色", db_constraint=False,
|
||||
help_text="关联角色")
|
||||
dept = models.ForeignKey(
|
||||
to="Dept",
|
||||
verbose_name="所属部门",
|
||||
on_delete=models.PROTECT,
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="关联部门",
|
||||
)
|
||||
objects = CustomUserManager()
|
||||
|
||||
def set_password(self, raw_password):
|
||||
super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest())
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_users"
|
||||
verbose_name = "用户表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class Post(CoreModel):
|
||||
name = models.CharField(null=False, max_length=64, verbose_name="岗位名称", help_text="岗位名称")
|
||||
code = models.CharField(max_length=32, verbose_name="岗位编码", help_text="岗位编码")
|
||||
sort = models.IntegerField(default=1, verbose_name="岗位顺序", help_text="岗位顺序")
|
||||
STATUS_CHOICES = (
|
||||
(0, "离职"),
|
||||
(1, "在职"),
|
||||
)
|
||||
status = models.IntegerField(choices=STATUS_CHOICES, default=1, verbose_name="岗位状态", help_text="岗位状态")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_post"
|
||||
verbose_name = "岗位表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("sort",)
|
||||
|
||||
|
||||
class Dept(CoreModel):
|
||||
name = models.CharField(max_length=64, verbose_name="部门名称", help_text="部门名称")
|
||||
key = models.CharField(max_length=64, unique=True, null=True, blank=True, verbose_name="关联字符",
|
||||
help_text="关联字符")
|
||||
sort = models.IntegerField(default=1, verbose_name="显示排序", help_text="显示排序")
|
||||
owner = models.CharField(max_length=32, verbose_name="负责人", null=True, blank=True, help_text="负责人")
|
||||
phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话")
|
||||
email = models.EmailField(max_length=32, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
|
||||
status = models.BooleanField(default=True, verbose_name="部门状态", null=True, blank=True, help_text="部门状态")
|
||||
parent = models.ForeignKey(
|
||||
to="Dept",
|
||||
on_delete=models.CASCADE,
|
||||
default=None,
|
||||
verbose_name="上级部门",
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="上级部门",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def recursion_all_dept(cls, dept_id: int, dept_all_list=None, dept_list=None):
|
||||
"""
|
||||
递归获取部门的所有下级部门
|
||||
:param dept_id: 需要获取的id
|
||||
:param dept_all_list: 所有列表
|
||||
:param dept_list: 递归list
|
||||
:return:
|
||||
"""
|
||||
if not dept_all_list:
|
||||
dept_all_list = Dept.objects.values("id", "parent")
|
||||
if dept_list is None:
|
||||
dept_list = [dept_id]
|
||||
for ele in dept_all_list:
|
||||
if ele.get("parent") == dept_id:
|
||||
dept_list.append(ele.get("id"))
|
||||
cls.recursion_all_dept(ele.get("id"), dept_all_list, dept_list)
|
||||
return list(set(dept_list))
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_dept"
|
||||
verbose_name = "部门表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("sort",)
|
||||
|
||||
|
||||
class Menu(CoreModel):
|
||||
parent = models.ForeignKey(
|
||||
to="Menu",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="上级菜单",
|
||||
null=True,
|
||||
blank=True,
|
||||
db_constraint=False,
|
||||
help_text="上级菜单",
|
||||
)
|
||||
icon = models.CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标")
|
||||
name = models.CharField(max_length=64, verbose_name="菜单名称", help_text="菜单名称")
|
||||
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
|
||||
ISLINK_CHOICES = (
|
||||
(0, "否"),
|
||||
(1, "是"),
|
||||
)
|
||||
is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")
|
||||
is_catalog = models.BooleanField(default=False, verbose_name="是否目录", help_text="是否目录")
|
||||
web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")
|
||||
component = models.CharField(max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址")
|
||||
component_name = models.CharField(max_length=50, verbose_name="组件名称", null=True, blank=True,
|
||||
help_text="组件名称")
|
||||
status = models.BooleanField(default=True, blank=True, verbose_name="菜单状态", help_text="菜单状态")
|
||||
cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")
|
||||
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",
|
||||
help_text="侧边栏中是否显示")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_menu"
|
||||
verbose_name = "菜单表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("sort",)
|
||||
|
||||
|
||||
class MenuButton(CoreModel):
|
||||
menu = models.ForeignKey(
|
||||
to="Menu",
|
||||
db_constraint=False,
|
||||
related_name="menuPermission",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="关联菜单",
|
||||
help_text="关联菜单",
|
||||
)
|
||||
name = models.CharField(max_length=64, verbose_name="名称", help_text="名称")
|
||||
value = models.CharField(unique=True, max_length=64, verbose_name="权限值", help_text="权限值")
|
||||
api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址")
|
||||
METHOD_CHOICES = (
|
||||
(0, "GET"),
|
||||
(1, "POST"),
|
||||
(2, "PUT"),
|
||||
(3, "DELETE"),
|
||||
)
|
||||
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True,
|
||||
help_text="接口请求方法")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_menu_button"
|
||||
verbose_name = "菜单权限表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-name",)
|
||||
|
||||
|
||||
class RoleMenuPermission(CoreModel):
|
||||
role = models.ForeignKey(
|
||||
to="Role",
|
||||
db_constraint=False,
|
||||
related_name="role_menu",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="关联角色",
|
||||
help_text="关联角色",
|
||||
)
|
||||
menu = models.ForeignKey(
|
||||
to="Menu",
|
||||
db_constraint=False,
|
||||
related_name="role_menu",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="关联菜单",
|
||||
help_text="关联菜单",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "role_menu_permission"
|
||||
verbose_name = "角色菜单权限表"
|
||||
verbose_name_plural = verbose_name
|
||||
# ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class RoleMenuButtonPermission(CoreModel):
|
||||
role = models.ForeignKey(
|
||||
to="Role",
|
||||
db_constraint=False,
|
||||
related_name="role_menu_button",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="关联角色",
|
||||
help_text="关联角色",
|
||||
)
|
||||
menu_button = models.ForeignKey(
|
||||
to="MenuButton",
|
||||
db_constraint=False,
|
||||
related_name="menu_button_permission",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name="关联菜单按钮",
|
||||
help_text="关联菜单按钮",
|
||||
null=True,
|
||||
blank=True
|
||||
)
|
||||
DATASCOPE_CHOICES = (
|
||||
(0, "仅本人数据权限"),
|
||||
(1, "本部门及以下数据权限"),
|
||||
(2, "本部门数据权限"),
|
||||
(3, "全部数据权限"),
|
||||
(4, "自定数据权限"),
|
||||
)
|
||||
data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围",
|
||||
help_text="数据权限范围")
|
||||
dept = models.ManyToManyField(to="Dept", blank=True, verbose_name="数据权限-关联部门", db_constraint=False,
|
||||
help_text="数据权限-关联部门")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "role_menu_button_permission"
|
||||
verbose_name = "角色按钮权限表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class Dictionary(CoreModel):
|
||||
TYPE_LIST = (
|
||||
(0, "text"),
|
||||
(1, "number"),
|
||||
(2, "date"),
|
||||
(3, "datetime"),
|
||||
(4, "time"),
|
||||
(5, "files"),
|
||||
(6, "boolean"),
|
||||
(7, "images"),
|
||||
)
|
||||
label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称")
|
||||
value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号",help_text="字典编号/实际值")
|
||||
parent = models.ForeignKey(
|
||||
to="self",
|
||||
related_name="sublist",
|
||||
db_constraint=False,
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="父级",
|
||||
help_text="父级",
|
||||
)
|
||||
type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型")
|
||||
color = models.CharField(max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色")
|
||||
is_value = models.BooleanField(default=False, verbose_name="是否为value值",
|
||||
help_text="是否为value值,用来做具体值存放")
|
||||
status = models.BooleanField(default=True, verbose_name="状态", help_text="状态")
|
||||
sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序")
|
||||
remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_dictionary"
|
||||
verbose_name = "字典表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("sort",)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
super().save(force_insert, force_update, using, update_fields)
|
||||
dispatch.refresh_dictionary() # 有更新则刷新字典配置
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
res = super().delete(using, keep_parents)
|
||||
dispatch.refresh_dictionary()
|
||||
return res
|
||||
|
||||
|
||||
class OperationLog(CoreModel):
|
||||
request_modular = models.CharField(max_length=64, verbose_name="请求模块", null=True, blank=True,
|
||||
help_text="请求模块")
|
||||
request_path = models.CharField(max_length=400, verbose_name="请求地址", null=True, blank=True,
|
||||
help_text="请求地址")
|
||||
request_body = models.TextField(verbose_name="请求参数", null=True, blank=True, help_text="请求参数")
|
||||
request_method = models.CharField(max_length=8, verbose_name="请求方式", null=True, blank=True,
|
||||
help_text="请求方式")
|
||||
request_msg = models.TextField(verbose_name="操作说明", null=True, blank=True, help_text="操作说明")
|
||||
request_ip = models.CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True,
|
||||
help_text="请求ip地址")
|
||||
request_browser = models.CharField(max_length=64, verbose_name="请求浏览器", null=True, blank=True,
|
||||
help_text="请求浏览器")
|
||||
response_code = models.CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True,
|
||||
help_text="响应状态码")
|
||||
request_os = models.CharField(max_length=64, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
|
||||
json_result = models.TextField(verbose_name="返回信息", null=True, blank=True, help_text="返回信息")
|
||||
status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_operation_log"
|
||||
verbose_name = "操作日志"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
def media_file_name(instance, filename):
|
||||
h = instance.md5sum
|
||||
basename, ext = os.path.splitext(filename)
|
||||
return os.path.join("files", h[:1], h[1:2], h + ext.lower())
|
||||
|
||||
|
||||
class FileList(CoreModel):
|
||||
name = models.CharField(max_length=200, null=True, blank=True, verbose_name="名称", help_text="名称")
|
||||
url = models.FileField(upload_to=media_file_name, null=True, blank=True,)
|
||||
file_url = models.CharField(max_length=255, blank=True, verbose_name="文件地址", help_text="文件地址")
|
||||
engine = models.CharField(max_length=100, default='local', blank=True, verbose_name="引擎", help_text="引擎")
|
||||
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")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
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
|
||||
if not self.file_url:
|
||||
url = media_file_name(self,self.name)
|
||||
self.file_url = f'media/{url}'
|
||||
super(FileList, self).save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_file_list"
|
||||
verbose_name = "文件管理"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class Area(CoreModel):
|
||||
name = models.CharField(max_length=100, verbose_name="名称", help_text="名称")
|
||||
code = models.CharField(max_length=20, verbose_name="地区编码", help_text="地区编码", unique=True, db_index=True)
|
||||
level = models.BigIntegerField(verbose_name="地区层级(1省份 2城市 3区县 4乡级)",
|
||||
help_text="地区层级(1省份 2城市 3区县 4乡级)")
|
||||
pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音")
|
||||
initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母")
|
||||
enable = models.BooleanField(default=True, verbose_name="是否启用", help_text="是否启用")
|
||||
pcode = models.ForeignKey(
|
||||
to="self",
|
||||
verbose_name="父地区编码",
|
||||
to_field="code",
|
||||
on_delete=models.CASCADE,
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="父地区编码",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_area"
|
||||
verbose_name = "地区表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("code",)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
||||
|
||||
class ApiWhiteList(CoreModel):
|
||||
url = models.CharField(max_length=200, help_text="url地址", verbose_name="url")
|
||||
METHOD_CHOICES = (
|
||||
(0, "GET"),
|
||||
(1, "POST"),
|
||||
(2, "PUT"),
|
||||
(3, "DELETE"),
|
||||
)
|
||||
method = models.IntegerField(default=0, verbose_name="接口请求方法", null=True, blank=True,
|
||||
help_text="接口请求方法")
|
||||
enable_datasource = models.BooleanField(default=True, verbose_name="激活数据权限", help_text="激活数据权限",
|
||||
blank=True)
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "api_white_list"
|
||||
verbose_name = "接口白名单"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class SystemConfig(CoreModel):
|
||||
parent = models.ForeignKey(
|
||||
to="self",
|
||||
verbose_name="父级",
|
||||
on_delete=models.CASCADE,
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="父级",
|
||||
)
|
||||
title = models.CharField(max_length=50, verbose_name="标题", help_text="标题")
|
||||
key = models.CharField(max_length=20, verbose_name="键", help_text="键", db_index=True)
|
||||
value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True)
|
||||
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
|
||||
status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态")
|
||||
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
|
||||
FORM_ITEM_TYPE_LIST = (
|
||||
(0, "text"),
|
||||
(1, "datetime"),
|
||||
(2, "date"),
|
||||
(3, "textarea"),
|
||||
(4, "select"),
|
||||
(5, "checkbox"),
|
||||
(6, "radio"),
|
||||
(7, "img"),
|
||||
(8, "file"),
|
||||
(9, "switch"),
|
||||
(10, "number"),
|
||||
(11, "array"),
|
||||
(12, "imgs"),
|
||||
(13, "foreignkey"),
|
||||
(14, "manytomany"),
|
||||
(15, "time"),
|
||||
)
|
||||
form_item_type = models.IntegerField(
|
||||
choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, blank=True
|
||||
)
|
||||
rule = models.JSONField(null=True, blank=True, verbose_name="校验规则", help_text="校验规则")
|
||||
placeholder = models.CharField(max_length=50, null=True, blank=True, verbose_name="提示信息", help_text="提示信息")
|
||||
setting = models.JSONField(null=True, blank=True, verbose_name="配置", help_text="配置")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_config"
|
||||
verbose_name = "系统配置表"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("sort",)
|
||||
unique_together = (("key", "parent_id"),)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.title}"
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||
super().save(force_insert, force_update, using, update_fields)
|
||||
dispatch.refresh_system_config() # 有更新则刷新系统配置
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
res = super().delete(using, keep_parents)
|
||||
dispatch.refresh_system_config()
|
||||
return res
|
||||
|
||||
|
||||
class LoginLog(CoreModel):
|
||||
LOGIN_TYPE_CHOICES = ((1, "普通登录"), (2, "微信扫码登录"),)
|
||||
username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名")
|
||||
ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip")
|
||||
agent = models.TextField(verbose_name="agent信息", null=True, blank=True, help_text="agent信息")
|
||||
browser = models.CharField(max_length=200, verbose_name="浏览器名", null=True, blank=True, help_text="浏览器名")
|
||||
os = models.CharField(max_length=200, verbose_name="操作系统", null=True, blank=True, help_text="操作系统")
|
||||
continent = models.CharField(max_length=50, verbose_name="州", null=True, blank=True, help_text="州")
|
||||
country = models.CharField(max_length=50, verbose_name="国家", null=True, blank=True, help_text="国家")
|
||||
province = models.CharField(max_length=50, verbose_name="省份", null=True, blank=True, help_text="省份")
|
||||
city = models.CharField(max_length=50, verbose_name="城市", null=True, blank=True, help_text="城市")
|
||||
district = models.CharField(max_length=50, verbose_name="县区", null=True, blank=True, help_text="县区")
|
||||
isp = models.CharField(max_length=50, verbose_name="运营商", null=True, blank=True, help_text="运营商")
|
||||
area_code = models.CharField(max_length=50, verbose_name="区域代码", null=True, blank=True, help_text="区域代码")
|
||||
country_english = models.CharField(max_length=50, verbose_name="英文全称", null=True, blank=True,
|
||||
help_text="英文全称")
|
||||
country_code = models.CharField(max_length=50, verbose_name="简称", null=True, blank=True, help_text="简称")
|
||||
longitude = models.CharField(max_length=50, verbose_name="经度", null=True, blank=True, help_text="经度")
|
||||
latitude = models.CharField(max_length=50, verbose_name="纬度", null=True, blank=True, help_text="纬度")
|
||||
login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型",
|
||||
help_text="登录类型")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "system_login_log"
|
||||
verbose_name = "登录日志"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class MessageCenter(CoreModel):
|
||||
title = models.CharField(max_length=100, verbose_name="标题", help_text="标题")
|
||||
content = models.TextField(verbose_name="内容", help_text="内容")
|
||||
target_type = models.IntegerField(default=0, verbose_name="目标类型", help_text="目标类型")
|
||||
target_user = models.ManyToManyField(to=Users, related_name='user', through='MessageCenterTargetUser',
|
||||
through_fields=('messagecenter', 'users'), blank=True, verbose_name="目标用户",
|
||||
help_text="目标用户")
|
||||
target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False,
|
||||
verbose_name="目标部门", help_text="目标部门")
|
||||
target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False,
|
||||
verbose_name="目标角色", help_text="目标角色")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "message_center"
|
||||
verbose_name = "消息中心"
|
||||
verbose_name_plural = verbose_name
|
||||
ordering = ("-create_datetime",)
|
||||
|
||||
|
||||
class MessageCenterTargetUser(CoreModel):
|
||||
users = models.ForeignKey(Users, related_name="target_user", on_delete=models.CASCADE, db_constraint=False,
|
||||
verbose_name="关联用户表", help_text="关联用户表")
|
||||
messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE, db_constraint=False,
|
||||
verbose_name="关联消息中心表", help_text="关联消息中心表")
|
||||
is_read = models.BooleanField(default=False, blank=True, null=True, verbose_name="是否已读", help_text="是否已读")
|
||||
|
||||
class Meta:
|
||||
db_table = table_prefix + "message_center_target_user"
|
||||
verbose_name = "消息中心目标用户表"
|
||||
verbose_name_plural = verbose_name
|
||||
1
backend/dvadmin/system/tests.py
Normal file
1
backend/dvadmin/system/tests.py
Normal file
@@ -0,0 +1 @@
|
||||
from django.test import TestCase
|
||||
50
backend/dvadmin/system/urls.py
Normal file
50
backend/dvadmin/system/urls.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from django.urls import path
|
||||
from rest_framework import routers
|
||||
|
||||
from dvadmin.system.views.api_white_list import ApiWhiteListViewSet
|
||||
from dvadmin.system.views.area import AreaViewSet
|
||||
from dvadmin.system.views.dept import DeptViewSet
|
||||
from dvadmin.system.views.dictionary import DictionaryViewSet
|
||||
from dvadmin.system.views.file_list import FileViewSet
|
||||
from dvadmin.system.views.login_log import LoginLogViewSet
|
||||
from dvadmin.system.views.menu import MenuViewSet
|
||||
from dvadmin.system.views.menu_button import MenuButtonViewSet
|
||||
from dvadmin.system.views.message_center import MessageCenterViewSet
|
||||
from dvadmin.system.views.operation_log import OperationLogViewSet
|
||||
from dvadmin.system.views.role import RoleViewSet
|
||||
from dvadmin.system.views.role_menu import RoleMenuPermissionViewSet
|
||||
from dvadmin.system.views.role_menu_button_permission import RoleMenuButtonPermissionViewSet
|
||||
from dvadmin.system.views.system_config import SystemConfigViewSet
|
||||
from dvadmin.system.views.user import UserViewSet
|
||||
|
||||
system_url = routers.SimpleRouter()
|
||||
system_url.register(r'menu', MenuViewSet)
|
||||
system_url.register(r'menu_button', MenuButtonViewSet)
|
||||
system_url.register(r'role', RoleViewSet)
|
||||
system_url.register(r'dept', DeptViewSet)
|
||||
system_url.register(r'user', UserViewSet)
|
||||
system_url.register(r'operation_log', OperationLogViewSet)
|
||||
system_url.register(r'dictionary', DictionaryViewSet)
|
||||
system_url.register(r'area', AreaViewSet)
|
||||
system_url.register(r'file', FileViewSet)
|
||||
system_url.register(r'api_white_list', ApiWhiteListViewSet)
|
||||
system_url.register(r'system_config', SystemConfigViewSet)
|
||||
system_url.register(r'message_center',MessageCenterViewSet)
|
||||
system_url.register(r'role_menu_button_permission', RoleMenuButtonPermissionViewSet)
|
||||
system_url.register(r'role_menu_permission', RoleMenuPermissionViewSet)
|
||||
|
||||
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('user/export/', UserViewSet.as_view({'post': 'export_data', })),
|
||||
path('user/import/', UserViewSet.as_view({'get': 'import_data', 'post': 'import_data'})),
|
||||
path('system_config/save_content/', SystemConfigViewSet.as_view({'put': 'save_content'})),
|
||||
path('system_config/get_association_table/', SystemConfigViewSet.as_view({'get': 'get_association_table'})),
|
||||
path('system_config/get_table_data/<int:pk>/', SystemConfigViewSet.as_view({'get': 'get_table_data'})),
|
||||
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'})),
|
||||
]
|
||||
urlpatterns += system_url.urls
|
||||
1
backend/dvadmin/system/util/pca-code.json
Normal file
1
backend/dvadmin/system/util/pca-code.json
Normal file
File diff suppressed because one or more lines are too long
39
backend/dvadmin/system/views/api_white_list.py
Normal file
39
backend/dvadmin/system/views/api_white_list.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2022/1/1 001 9:34
|
||||
@Remark:
|
||||
"""
|
||||
from dvadmin.system.models import ApiWhiteList
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class ApiWhiteListSerializer(CustomModelSerializer):
|
||||
"""
|
||||
接口白名单-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ApiWhiteList
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ApiWhiteListViewSet(CustomModelViewSet):
|
||||
"""
|
||||
接口白名单
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = ApiWhiteList.objects.all()
|
||||
serializer_class = ApiWhiteListSerializer
|
||||
# permission_classes = []
|
||||
71
backend/dvadmin/system/views/area.py
Normal file
71
backend/dvadmin/system/views/area.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.db.models import Q
|
||||
from rest_framework import serializers
|
||||
|
||||
from dvadmin.system.models import Area
|
||||
from dvadmin.utils.json_response import SuccessResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class AreaSerializer(CustomModelSerializer):
|
||||
"""
|
||||
地区-序列化器
|
||||
"""
|
||||
pcode_count = serializers.SerializerMethodField(read_only=True)
|
||||
hasChild = serializers.SerializerMethodField()
|
||||
def get_pcode_count(self, instance: Area):
|
||||
return Area.objects.filter(pcode=instance).count()
|
||||
def get_hasChild(self, instance):
|
||||
hasChild = Area.objects.filter(pcode=instance.code)
|
||||
if hasChild:
|
||||
return True
|
||||
return False
|
||||
class Meta:
|
||||
model = Area
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class AreaCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
地区管理 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Area
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class AreaViewSet(CustomModelViewSet):
|
||||
"""
|
||||
地区管理接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = Area.objects.all()
|
||||
serializer_class = AreaSerializer
|
||||
extra_filter_class = []
|
||||
|
||||
def get_queryset(self):
|
||||
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:
|
||||
if pcode:
|
||||
queryset = self.queryset.filter(enable=True, pcode=pcode)
|
||||
else:
|
||||
queryset = self.queryset.filter(enable=True)
|
||||
else:
|
||||
queryset = self.queryset.filter(enable=True, pcode__isnull=True)
|
||||
return queryset
|
||||
|
||||
157
backend/dvadmin/system/views/dept.py
Normal file
157
backend/dvadmin/system/views/dept.py
Normal file
@@ -0,0 +1,157 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: H0nGzA1
|
||||
@contact: QQ:2505811377
|
||||
@Remark: 部门管理
|
||||
"""
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from dvadmin.system.models import Dept, RoleMenuButtonPermission
|
||||
from dvadmin.utils.json_response import DetailResponse, SuccessResponse
|
||||
from dvadmin.utils.permission import AnonymousUserPermission
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class DeptSerializer(CustomModelSerializer):
|
||||
"""
|
||||
部门-序列化器
|
||||
"""
|
||||
parent_name = serializers.CharField(read_only=True, source='parent.name')
|
||||
status_label = serializers.SerializerMethodField()
|
||||
has_children = serializers.SerializerMethodField()
|
||||
hasChild = serializers.SerializerMethodField()
|
||||
|
||||
def get_hasChild(self, instance):
|
||||
hasChild = Dept.objects.filter(parent=instance.id)
|
||||
if hasChild:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_status_label(self, obj: Dept):
|
||||
if obj.status:
|
||||
return "启用"
|
||||
return "禁用"
|
||||
|
||||
def get_has_children(self, obj: Dept):
|
||||
return Dept.objects.filter(parent_id=obj.id).count()
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
fields = '__all__'
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class DeptImportSerializer(CustomModelSerializer):
|
||||
"""
|
||||
部门-导入-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
fields = '__all__'
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DeptCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
部门管理 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
def create(self, validated_data):
|
||||
value = validated_data.get('parent',None)
|
||||
if value is None:
|
||||
validated_data['parent'] = self.request.user.dept
|
||||
instance = super().create(validated_data)
|
||||
instance.dept_belong_id = instance.id
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = Dept
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class DeptViewSet(CustomModelViewSet):
|
||||
"""
|
||||
部门管理接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = Dept.objects.all()
|
||||
serializer_class = DeptSerializer
|
||||
create_serializer_class = DeptCreateUpdateSerializer
|
||||
update_serializer_class = DeptCreateUpdateSerializer
|
||||
filter_fields = ['name', 'id', 'parent']
|
||||
search_fields = []
|
||||
# extra_filter_class = []
|
||||
import_serializer_class = DeptImportSerializer
|
||||
import_field_dict = {
|
||||
"name": "部门名称",
|
||||
"key": "部门标识",
|
||||
}
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
# 如果懒加载,则只返回父级
|
||||
request.query_params._mutable = True
|
||||
params = request.query_params
|
||||
parent = params.get('parent', None)
|
||||
page = params.get('page', None)
|
||||
limit = params.get('limit', None)
|
||||
if page:
|
||||
del params['page']
|
||||
if limit:
|
||||
del params['limit']
|
||||
if params:
|
||||
if parent:
|
||||
queryset = self.queryset.filter(status=True, parent=parent)
|
||||
else:
|
||||
queryset = self.queryset.filter(status=True)
|
||||
else:
|
||||
queryset = self.queryset.filter(status=True, parent__isnull=True)
|
||||
queryset = self.filter_queryset(queryset)
|
||||
serializer = DeptSerializer(queryset, many=True, request=request)
|
||||
data = serializer.data
|
||||
return SuccessResponse(data=data)
|
||||
|
||||
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated], extra_filter_class=[])
|
||||
def dept_lazy_tree(self, request, *args, **kwargs):
|
||||
parent = self.request.query_params.get('parent')
|
||||
is_superuser = request.user.is_superuser
|
||||
if is_superuser:
|
||||
queryset = Dept.objects.values('id', 'name', 'parent')
|
||||
else:
|
||||
role_ids = request.user.role.values_list('id',flat=True)
|
||||
data_range = RoleMenuButtonPermission.objects.filter(role__in=role_ids).values_list('data_range', flat=True)
|
||||
user_dept_id = request.user.dept.id
|
||||
dept_list = [user_dept_id]
|
||||
data_range_list = list(set(data_range))
|
||||
for item in data_range_list:
|
||||
if item in [0,2]:
|
||||
dept_list = [user_dept_id]
|
||||
elif item == 1:
|
||||
dept_list = Dept.recursion_dept_info(dept_id=user_dept_id)
|
||||
elif item == 3:
|
||||
dept_list = Dept.objects.values_list('id',flat=True)
|
||||
elif item == 4:
|
||||
dept_list = request.user.role.values_list('dept',flat=True)
|
||||
else:
|
||||
dept_list = []
|
||||
queryset = Dept.objects.filter(id__in=dept_list).values('id', 'name', 'parent')
|
||||
return DetailResponse(data=queryset, msg="获取成功")
|
||||
|
||||
|
||||
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated],extra_filter_class=[])
|
||||
def all_dept(self, request, *args, **kwargs):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
data = queryset.filter(status=True).order_by('sort').values('name', 'id', 'parent')
|
||||
return DetailResponse(data=data, msg="获取成功")
|
||||
107
backend/dvadmin/system/views/dictionary.py
Normal file
107
backend/dvadmin/system/views/dictionary.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2021/6/3 003 0:30
|
||||
@Remark: 字典管理
|
||||
"""
|
||||
from rest_framework import serializers
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from application import dispatch
|
||||
from dvadmin.system.models import Dictionary
|
||||
from dvadmin.utils.json_response import SuccessResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class DictionarySerializer(CustomModelSerializer):
|
||||
"""
|
||||
字典-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Dictionary
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DictionaryCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
字典管理 创建/更新时的列化器
|
||||
"""
|
||||
value = serializers.CharField(max_length=100)
|
||||
|
||||
def validate_value(self, value):
|
||||
"""
|
||||
在父级的字典编号验证重复性
|
||||
"""
|
||||
initial_data = self.initial_data
|
||||
parent = initial_data.get('parent',None)
|
||||
if parent is None:
|
||||
unique = Dictionary.objects.filter(value=value).exists()
|
||||
if unique:
|
||||
raise serializers.ValidationError("字典编号不能重复")
|
||||
return value
|
||||
|
||||
class Meta:
|
||||
model = Dictionary
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class DictionaryViewSet(CustomModelViewSet):
|
||||
"""
|
||||
字典管理接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = Dictionary.objects.all()
|
||||
serializer_class = DictionarySerializer
|
||||
create_serializer_class = DictionaryCreateUpdateSerializer
|
||||
extra_filter_class = []
|
||||
search_fields = ['label']
|
||||
|
||||
def get_queryset(self):
|
||||
if self.action =='list':
|
||||
params = self.request.query_params
|
||||
parent = params.get('parent', None)
|
||||
if params:
|
||||
if parent:
|
||||
queryset = self.queryset.filter(parent=parent)
|
||||
else:
|
||||
queryset = self.queryset.filter(parent__isnull=True)
|
||||
else:
|
||||
queryset = self.queryset.filter(parent__isnull=True)
|
||||
return queryset
|
||||
else:
|
||||
return self.queryset
|
||||
|
||||
|
||||
class InitDictionaryViewSet(APIView):
|
||||
"""
|
||||
获取初始化配置
|
||||
"""
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
queryset = Dictionary.objects.all()
|
||||
|
||||
def get(self, request):
|
||||
dictionary_key = self.request.query_params.get('dictionary_key')
|
||||
if dictionary_key:
|
||||
if dictionary_key == 'all':
|
||||
data = [ele for ele in dispatch.get_dictionary_config().values()]
|
||||
if not data:
|
||||
dispatch.refresh_dictionary()
|
||||
data = [ele for ele in dispatch.get_dictionary_config().values()]
|
||||
else:
|
||||
data = self.queryset.filter(parent__value=dictionary_key, status=True).values('label', 'value', 'type',
|
||||
'color')
|
||||
return SuccessResponse(data=data, msg="获取成功")
|
||||
return SuccessResponse(data=[], msg="获取成功")
|
||||
79
backend/dvadmin/system/views/file_list.py
Normal file
79
backend/dvadmin/system/views/file_list.py
Normal file
@@ -0,0 +1,79 @@
|
||||
import hashlib
|
||||
import mimetypes
|
||||
|
||||
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.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class FileSerializer(CustomModelSerializer):
|
||||
url = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
def get_url(self, instance):
|
||||
# return 'media/' + str(instance.url)
|
||||
return instance.file_url or (f'media/{str(instance.url)}')
|
||||
|
||||
class Meta:
|
||||
model = FileList
|
||||
fields = "__all__"
|
||||
|
||||
def create(self, validated_data):
|
||||
file_engine = dispatch.get_system_config_values("fileStorageConfig.file_engine") or 'local'
|
||||
file_backup = dispatch.get_system_config_values("fileStorageConfig.file_backup")
|
||||
file = self.initial_data.get('file')
|
||||
file_size = file.size
|
||||
validated_data['name'] = str(file)
|
||||
validated_data['size'] = file_size
|
||||
md5 = hashlib.md5()
|
||||
for chunk in file.chunks():
|
||||
md5.update(chunk)
|
||||
validated_data['md5sum'] = md5.hexdigest()
|
||||
validated_data['engine'] = file_engine
|
||||
validated_data['mime_type'] = file.content_type
|
||||
if file_backup:
|
||||
validated_data['url'] = file
|
||||
if file_engine == 'oss':
|
||||
from dvadmin_cloud_storage.views.aliyun import ali_oss_upload
|
||||
file_path = ali_oss_upload(file)
|
||||
if file_path:
|
||||
validated_data['file_url'] = file_path
|
||||
else:
|
||||
raise ValueError("上传失败")
|
||||
elif file_engine == 'cos':
|
||||
from dvadmin_cloud_storage.views.tencent import tencent_cos_upload
|
||||
file_path = tencent_cos_upload(file)
|
||||
if file_path:
|
||||
validated_data['file_url'] = file_path
|
||||
else:
|
||||
raise ValueError("上传失败")
|
||||
else:
|
||||
validated_data['url'] = file
|
||||
# 审计字段
|
||||
try:
|
||||
request_user = self.request.user
|
||||
validated_data['dept_belong_id'] = request_user.dept.id
|
||||
validated_data['creator'] = request_user.id
|
||||
validated_data['modifier'] = request_user.id
|
||||
except:
|
||||
pass
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class FileViewSet(CustomModelViewSet):
|
||||
"""
|
||||
文件管理接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = FileList.objects.all()
|
||||
serializer_class = FileSerializer
|
||||
filter_fields = ['name', ]
|
||||
permission_classes = []
|
||||
251
backend/dvadmin/system/views/login.py
Normal file
251
backend/dvadmin/system/views/login.py
Normal file
@@ -0,0 +1,251 @@
|
||||
import base64
|
||||
import hashlib
|
||||
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.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.views import APIView
|
||||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
||||
from django.conf import settings
|
||||
from application import dispatch
|
||||
from dvadmin.system.models import Users
|
||||
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
|
||||
from dvadmin.utils.request_util import save_login_log
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.validator import CustomValidationError
|
||||
|
||||
|
||||
class CaptchaView(APIView):
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
|
||||
@swagger_auto_schema(
|
||||
responses={"200": openapi.Response("获取成功")},
|
||||
security=[],
|
||||
operation_id="captcha-get",
|
||||
operation_description="验证码获取",
|
||||
)
|
||||
def get(self, request):
|
||||
data = {}
|
||||
if dispatch.get_system_config_values("base.captcha_state"):
|
||||
hashkey = CaptchaStore.generate_key()
|
||||
id = CaptchaStore.objects.filter(hashkey=hashkey).first().id
|
||||
imgage = captcha_image(request, hashkey)
|
||||
# 将图片转换为base64
|
||||
image_base = base64.b64encode(imgage.content)
|
||||
data = {
|
||||
"key": id,
|
||||
"image_base": "data:image/png;base64," + image_base.decode("utf-8"),
|
||||
}
|
||||
return DetailResponse(data=data)
|
||||
|
||||
|
||||
class LoginSerializer(TokenObtainPairSerializer):
|
||||
"""
|
||||
登录的序列化器:
|
||||
重写djangorestframework-simplejwt的序列化器
|
||||
"""
|
||||
captcha = serializers.CharField(
|
||||
max_length=6, required=False, allow_null=True, allow_blank=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
default_error_messages = {"no_active_account": _("账号/密码错误")}
|
||||
|
||||
def validate(self, attrs):
|
||||
captcha = self.initial_data.get("captcha", None)
|
||||
if dispatch.get_system_config_values("base.captcha_state"):
|
||||
if captcha is None:
|
||||
raise CustomValidationError("验证码不能为空")
|
||||
self.image_code = CaptchaStore.objects.filter(
|
||||
id=self.initial_data["captchaKey"]
|
||||
).first()
|
||||
five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
|
||||
if self.image_code and five_minute_ago > self.image_code.expiration:
|
||||
self.image_code and self.image_code.delete()
|
||||
raise CustomValidationError("验证码过期")
|
||||
else:
|
||||
if self.image_code and (
|
||||
self.image_code.response == captcha
|
||||
or self.image_code.challenge == captcha
|
||||
):
|
||||
self.image_code and self.image_code.delete()
|
||||
else:
|
||||
self.image_code and self.image_code.delete()
|
||||
raise CustomValidationError("图片验证码错误")
|
||||
|
||||
user = Users.objects.get(username=attrs['username'])
|
||||
if not user.is_active:
|
||||
raise CustomValidationError("账号被锁定")
|
||||
|
||||
data = super().validate(attrs)
|
||||
data["name"] = self.user.name
|
||||
data["userId"] = self.user.id
|
||||
data["avatar"] = self.user.avatar
|
||||
data['user_type'] = self.user.user_type
|
||||
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:
|
||||
data['role_info'] = role.values('id', 'name', 'key')
|
||||
request = self.context.get("request")
|
||||
request.user = self.user
|
||||
# 记录登录日志
|
||||
save_login_log(request=request)
|
||||
return {"code": 2000, "msg": "请求成功", "data": data}
|
||||
|
||||
|
||||
class LoginView(TokenObtainPairView):
|
||||
"""
|
||||
登录接口
|
||||
"""
|
||||
serializer_class = LoginSerializer
|
||||
permission_classes = []
|
||||
|
||||
# def post(self, request, *args, **kwargs):
|
||||
# # username可能携带的不止是用户名,可能还是用户的其它唯一标识 手机号 邮箱
|
||||
# username = request.data.get('username',None)
|
||||
# if username is None:
|
||||
# return ErrorResponse(msg="参数错误")
|
||||
# password = request.data.get('password',None)
|
||||
# if password is None:
|
||||
# return ErrorResponse(msg="参数错误")
|
||||
# captcha = request.data.get('captcha',None)
|
||||
# if captcha is None:
|
||||
# return ErrorResponse(msg="参数错误")
|
||||
# captchaKey = request.data.get('captchaKey',None)
|
||||
# if captchaKey is None:
|
||||
# return ErrorResponse(msg="参数错误")
|
||||
# if dispatch.get_system_config_values("base.captcha_state"):
|
||||
# if captcha is None:
|
||||
# raise CustomValidationError("验证码不能为空")
|
||||
# self.image_code = CaptchaStore.objects.filter(
|
||||
# id=captchaKey
|
||||
# ).first()
|
||||
# five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
|
||||
# if self.image_code and five_minute_ago > self.image_code.expiration:
|
||||
# self.image_code and self.image_code.delete()
|
||||
# raise CustomValidationError("验证码过期")
|
||||
# else:
|
||||
# if self.image_code and (
|
||||
# self.image_code.response == captcha
|
||||
# or self.image_code.challenge == captcha
|
||||
# ):
|
||||
# self.image_code and self.image_code.delete()
|
||||
# else:
|
||||
# self.image_code and self.image_code.delete()
|
||||
# raise CustomValidationError("图片验证码错误")
|
||||
# try:
|
||||
# # 手动通过 user 签发 jwt-token
|
||||
# user = Users.objects.get(username=username)
|
||||
# except:
|
||||
# return DetailResponse(msg='该账号未注册')
|
||||
# # 获得用户后,校验密码并签发token
|
||||
# print(make_password(password),user.password)
|
||||
# if check_password(make_password(password),user.password):
|
||||
# return DetailResponse(msg='密码错误')
|
||||
# result = {
|
||||
# "name":user.name,
|
||||
# "userId":user.id,
|
||||
# "avatar":user.avatar,
|
||||
# }
|
||||
# dept = getattr(user, 'dept', None)
|
||||
# if dept:
|
||||
# result['dept_info'] = {
|
||||
# 'dept_id': dept.id,
|
||||
# 'dept_name': dept.name,
|
||||
# 'dept_key': dept.key
|
||||
# }
|
||||
# role = getattr(user, 'role', None)
|
||||
# if role:
|
||||
# result['role_info'] = role.values('id', 'name', 'key')
|
||||
# refresh = LoginSerializer.get_token(user)
|
||||
# result["refresh"] = str(refresh)
|
||||
# result["access"] = str(refresh.access_token)
|
||||
# # 记录登录日志
|
||||
# request.user = user
|
||||
# save_login_log(request=request)
|
||||
# return DetailResponse(data=result,msg="获取成功")
|
||||
|
||||
|
||||
class LoginTokenSerializer(TokenObtainPairSerializer):
|
||||
"""
|
||||
登录的序列化器:
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
default_error_messages = {"no_active_account": _("账号/密码不正确")}
|
||||
|
||||
def validate(self, attrs):
|
||||
if not getattr(settings, "LOGIN_NO_CAPTCHA_AUTH", False):
|
||||
return {"code": 4000, "msg": "该接口暂未开通!", "data": None}
|
||||
data = super().validate(attrs)
|
||||
data["name"] = self.user.name
|
||||
data["userId"] = self.user.id
|
||||
return {"code": 2000, "msg": "请求成功", "data": data}
|
||||
|
||||
|
||||
class LoginTokenView(TokenObtainPairView):
|
||||
"""
|
||||
登录获取token接口
|
||||
"""
|
||||
|
||||
serializer_class = LoginTokenSerializer
|
||||
permission_classes = []
|
||||
|
||||
|
||||
class LogoutView(APIView):
|
||||
def post(self, request):
|
||||
return DetailResponse(msg="注销成功")
|
||||
|
||||
|
||||
class ApiLoginSerializer(CustomModelSerializer):
|
||||
"""接口文档登录-序列化器"""
|
||||
|
||||
username = serializers.CharField()
|
||||
password = serializers.CharField()
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
fields = ["username", "password"]
|
||||
|
||||
|
||||
class ApiLogin(APIView):
|
||||
"""接口文档的登录接口"""
|
||||
|
||||
serializer_class = ApiLoginSerializer
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
|
||||
def post(self, request):
|
||||
username = request.data.get("username")
|
||||
password = request.data.get("password")
|
||||
user_obj = auth.authenticate(
|
||||
request,
|
||||
username=username,
|
||||
password=hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),
|
||||
)
|
||||
if user_obj:
|
||||
login(request, user_obj)
|
||||
return redirect("/")
|
||||
else:
|
||||
return ErrorResponse(msg="账号/密码错误")
|
||||
36
backend/dvadmin/system/views/login_log.py
Normal file
36
backend/dvadmin/system/views/login_log.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2021/6/3 003 0:30
|
||||
@Remark: 按钮权限管理
|
||||
"""
|
||||
from dvadmin.system.models import LoginLog
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class LoginLogSerializer(CustomModelSerializer):
|
||||
"""
|
||||
登录日志权限-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = LoginLog
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class LoginLogViewSet(CustomModelViewSet):
|
||||
"""
|
||||
登录日志接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = LoginLog.objects.all()
|
||||
serializer_class = LoginLogSerializer
|
||||
extra_filter_class = []
|
||||
152
backend/dvadmin/system/views/menu.py
Normal file
152
backend/dvadmin/system/views/menu.py
Normal file
@@ -0,0 +1,152 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2021/6/1 001 22:38
|
||||
@Remark: 菜单模块
|
||||
"""
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from dvadmin.system.models import Menu, MenuButton, RoleMenuPermission
|
||||
from dvadmin.utils.json_response import SuccessResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class MenuSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单表的简单序列化器
|
||||
"""
|
||||
menuPermission = serializers.SerializerMethodField(read_only=True)
|
||||
hasChild = serializers.SerializerMethodField()
|
||||
|
||||
def get_menuPermission(self, instance):
|
||||
queryset = instance.menuPermission.order_by('-name').values_list('name', flat=True)
|
||||
if queryset:
|
||||
return queryset
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_hasChild(self, instance):
|
||||
hasChild = Menu.objects.filter(parent=instance.id)
|
||||
if hasChild:
|
||||
return True
|
||||
return False
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class MenuCreateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单表的创建序列化器
|
||||
"""
|
||||
name = serializers.CharField(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class WebRouterSerializer(CustomModelSerializer):
|
||||
"""
|
||||
前端菜单路由的简单序列化器
|
||||
"""
|
||||
path = serializers.CharField(source="web_path")
|
||||
title = serializers.CharField(source="name")
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = (
|
||||
'id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link', 'is_catalog', 'web_path', 'component',
|
||||
'component_name', 'cache', 'visible', 'status')
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class MenuViewSet(CustomModelViewSet):
|
||||
"""
|
||||
菜单管理接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = Menu.objects.all()
|
||||
serializer_class = MenuSerializer
|
||||
create_serializer_class = MenuCreateSerializer
|
||||
update_serializer_class = MenuCreateSerializer
|
||||
search_fields = ['name', 'status']
|
||||
filter_fields = ['parent', 'name', 'status', 'is_link', 'visible', 'cache', 'is_catalog']
|
||||
|
||||
# extra_filter_class = []
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[])
|
||||
def web_router(self, request):
|
||||
"""用于前端获取当前角色的路由"""
|
||||
user = request.user
|
||||
is_admin = user.role.values_list('admin', flat=True)
|
||||
if user.is_superuser or True in is_admin:
|
||||
queryset = self.queryset.filter(status=1)
|
||||
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)
|
||||
print("role_list", role_list)
|
||||
print("menu_list",menu_list)
|
||||
queryset = Menu.objects.filter(id__in=menu_list)
|
||||
print(queryset)
|
||||
serializer = WebRouterSerializer(queryset, many=True, request=request)
|
||||
data = serializer.data
|
||||
return SuccessResponse(data=data, total=len(data), msg="获取成功")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[])
|
||||
def get_all_menu(self, request):
|
||||
"""用于菜单管理获取所有的菜单"""
|
||||
user = request.user
|
||||
queryset = self.queryset.all()
|
||||
if not user.is_superuser:
|
||||
role_list = user.role.values_list('id', flat=True)
|
||||
menu_list = RoleMenuPermission.objects.filter(role__in=role_list).values_list('menu_id')
|
||||
queryset = Menu.objects.filter(id__in=menu_list)
|
||||
serializer = WebRouterSerializer(queryset, many=True, request=request)
|
||||
data = serializer.data
|
||||
return SuccessResponse(data=data, total=len(data), msg="获取成功")
|
||||
|
||||
@action(methods=['POST'], detail=False, permission_classes=[])
|
||||
def drag_menu(self, request):
|
||||
"""前端拖拽菜单之后重写parent"""
|
||||
menu_id = request.data['menu_id']
|
||||
parent_id = request.data['parent_id']
|
||||
menu = Menu.objects.get(id=menu_id)
|
||||
menu.parent_id = parent_id
|
||||
menu.save()
|
||||
|
||||
return SuccessResponse(data=[], msg="拖拽菜单成功")
|
||||
|
||||
def list(self, request):
|
||||
"""懒加载"""
|
||||
request.query_params._mutable = True
|
||||
params = request.query_params
|
||||
parent = params.get('parent', None)
|
||||
page = params.get('page', None)
|
||||
limit = params.get('limit', None)
|
||||
if page:
|
||||
del params['page']
|
||||
if limit:
|
||||
del params['limit']
|
||||
if params:
|
||||
if parent:
|
||||
queryset = self.queryset.filter(parent=parent)
|
||||
else:
|
||||
queryset = self.queryset.filter()
|
||||
else:
|
||||
queryset = self.queryset.filter(parent__isnull=True)
|
||||
queryset = self.filter_queryset(queryset)
|
||||
serializer = MenuSerializer(queryset, many=True, request=request)
|
||||
data = serializer.data
|
||||
return SuccessResponse(data=data)
|
||||
72
backend/dvadmin/system/views/menu_button.py
Normal file
72
backend/dvadmin/system/views/menu_button.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2021/6/3 003 0:30
|
||||
@Remark: 菜单按钮管理
|
||||
"""
|
||||
from django.db.models import F
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from dvadmin.system.models import MenuButton, RoleMenuButtonPermission
|
||||
from dvadmin.utils.json_response import DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class MenuButtonSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = MenuButton
|
||||
fields = ['id', 'name', 'value', 'api', 'method','menu']
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
||||
|
||||
class MenuButtonCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = MenuButton
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class MenuButtonViewSet(CustomModelViewSet):
|
||||
"""
|
||||
菜单按钮接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = MenuButton.objects.all()
|
||||
serializer_class = MenuButtonSerializer
|
||||
create_serializer_class = MenuButtonCreateUpdateSerializer
|
||||
update_serializer_class = MenuButtonCreateUpdateSerializer
|
||||
extra_filter_class = []
|
||||
|
||||
@action(methods=['get'],detail=False,permission_classes=[IsAuthenticated])
|
||||
def menu_button_all_permission(self,request):
|
||||
"""
|
||||
获取所有的按钮权限
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
is_superuser = request.user.is_superuser
|
||||
is_admin = request.user.role.values_list('admin', flat=True)
|
||||
if is_superuser or True in is_admin:
|
||||
queryset = MenuButton.objects.values_list('value',flat=True)
|
||||
else:
|
||||
role_id = request.user.role.values_list('id', flat=True)
|
||||
queryset = RoleMenuButtonPermission.objects.filter(role__in=role_id).values_list('menu_button__value',flat=True).distinct()
|
||||
return DetailResponse(data=queryset)
|
||||
218
backend/dvadmin/system/views/message_center.py
Normal file
218
backend/dvadmin/system/views/message_center.py
Normal file
@@ -0,0 +1,218 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
|
||||
from asgiref.sync import async_to_sync
|
||||
from channels.layers import get_channel_layer
|
||||
from django_restql.fields import DynamicSerializerMethodField
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action, permission_classes
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
|
||||
from dvadmin.system.models import MessageCenter, Users, MessageCenterTargetUser
|
||||
from dvadmin.utils.json_response import SuccessResponse, DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class MessageCenterSerializer(CustomModelSerializer):
|
||||
"""
|
||||
消息中心-序列化器
|
||||
"""
|
||||
role_info = DynamicSerializerMethodField()
|
||||
user_info = DynamicSerializerMethodField()
|
||||
dept_info = DynamicSerializerMethodField()
|
||||
is_read = serializers.BooleanField(read_only=True, source='target_user__is_read')
|
||||
|
||||
def get_role_info(self, instance, parsed_query):
|
||||
roles = instance.target_role.all()
|
||||
# You can do what ever you want in here
|
||||
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||
from dvadmin.system.views.role import RoleSerializer
|
||||
serializer = RoleSerializer(
|
||||
roles,
|
||||
many=True,
|
||||
parsed_query=parsed_query
|
||||
)
|
||||
return serializer.data
|
||||
|
||||
def get_user_info(self, instance, parsed_query):
|
||||
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
|
||||
from dvadmin.system.views.user import UserSerializer
|
||||
serializer = UserSerializer(
|
||||
users,
|
||||
many=True,
|
||||
parsed_query=parsed_query
|
||||
)
|
||||
return serializer.data
|
||||
|
||||
def get_dept_info(self, instance, parsed_query):
|
||||
dept = instance.target_dept.all()
|
||||
# You can do what ever you want in here
|
||||
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||
from dvadmin.system.views.dept import DeptSerializer
|
||||
serializer = DeptSerializer(
|
||||
dept,
|
||||
many=True,
|
||||
parsed_query=parsed_query
|
||||
)
|
||||
return serializer.data
|
||||
|
||||
class Meta:
|
||||
model = MessageCenter
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class MessageCenterTargetUserSerializer(CustomModelSerializer):
|
||||
"""
|
||||
目标用户序列化器-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = MessageCenterTargetUser
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class MessageCenterTargetUserListSerializer(CustomModelSerializer):
|
||||
"""
|
||||
目标用户序列化器-序列化器
|
||||
"""
|
||||
is_read = serializers.SerializerMethodField()
|
||||
|
||||
def get_is_read(self, instance):
|
||||
user_id = self.request.user.id
|
||||
message_center_id = instance.id
|
||||
queryset = MessageCenterTargetUser.objects.filter(messagecenter__id=message_center_id, users_id=user_id).first()
|
||||
if queryset:
|
||||
return queryset.is_read
|
||||
return False
|
||||
|
||||
class Meta:
|
||||
model = MessageCenter
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
def websocket_push(user_id, message):
|
||||
"""
|
||||
主动推送消息
|
||||
"""
|
||||
username = "user_" + str(user_id)
|
||||
channel_layer = get_channel_layer()
|
||||
async_to_sync(channel_layer.group_send)(
|
||||
username,
|
||||
{
|
||||
"type": "push.message",
|
||||
"json": message
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class MessageCenterCreateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
消息中心-新增-序列化器
|
||||
"""
|
||||
|
||||
def save(self, **kwargs):
|
||||
data = super().save(**kwargs)
|
||||
initial_data = self.initial_data
|
||||
target_type = initial_data.get('target_type')
|
||||
# 在保存之前,根据目标类型,把目标用户查询出来并保存
|
||||
users = initial_data.get('target_user', [])
|
||||
if target_type in [1]: # 按角色
|
||||
target_role = initial_data.get('target_role', [])
|
||||
users = Users.objects.filter(role__id__in=target_role).values_list('id', flat=True)
|
||||
if target_type in [2]: # 按部门
|
||||
target_dept = initial_data.get('target_dept', [])
|
||||
users = Users.objects.filter(dept__id__in=target_dept).values_list('id', flat=True)
|
||||
if target_type in [3]: # 系统通知
|
||||
users = Users.objects.values_list('id', flat=True)
|
||||
targetuser_data = []
|
||||
for user in users:
|
||||
targetuser_data.append({
|
||||
"messagecenter": data.id,
|
||||
"users": user
|
||||
})
|
||||
targetuser_instance = MessageCenterTargetUserSerializer(data=targetuser_data, many=True, request=self.request)
|
||||
targetuser_instance.is_valid(raise_exception=True)
|
||||
targetuser_instance.save()
|
||||
for user in users:
|
||||
unread_count = MessageCenterTargetUser.objects.filter(users__id=user, is_read=False).count()
|
||||
websocket_push(user, message={"sender": 'system', "contentType": 'SYSTEM',
|
||||
"content": '您有一条新消息~', "unread": unread_count})
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = MessageCenter
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class MessageCenterViewSet(CustomModelViewSet):
|
||||
"""
|
||||
消息中心接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = MessageCenter.objects.order_by('create_datetime')
|
||||
serializer_class = MessageCenterSerializer
|
||||
create_serializer_class = MessageCenterCreateSerializer
|
||||
extra_filter_backends = []
|
||||
|
||||
def get_queryset(self):
|
||||
if self.action == 'list':
|
||||
return MessageCenter.objects.filter(creator=self.request.user.id).all()
|
||||
return MessageCenter.objects.all()
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
"""
|
||||
重写查看
|
||||
"""
|
||||
pk = kwargs.get('pk')
|
||||
user_id = self.request.user.id
|
||||
queryset = MessageCenterTargetUser.objects.filter(users__id=user_id, messagecenter__id=pk).first()
|
||||
if queryset:
|
||||
queryset.is_read = True
|
||||
queryset.save()
|
||||
instance = self.get_object()
|
||||
serializer = self.get_serializer(instance)
|
||||
# 主动推送消息
|
||||
unread_count = MessageCenterTargetUser.objects.filter(users__id=user_id, is_read=False).count()
|
||||
websocket_push(user_id, message={"sender": 'system', "contentType": 'TEXT',
|
||||
"content": '您查看了一条消息~', "unread": unread_count})
|
||||
return DetailResponse(data=serializer.data, msg="获取成功")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def get_self_receive(self, request):
|
||||
"""
|
||||
获取接收到的消息
|
||||
"""
|
||||
self_user_id = self.request.user.id
|
||||
# queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('-create_datetime')
|
||||
queryset = MessageCenter.objects.filter(target_user__id=self_user_id)
|
||||
# queryset = self.filter_queryset(queryset)
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
serializer = MessageCenterTargetUserListSerializer(page, many=True, request=request)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
serializer = MessageCenterTargetUserListSerializer(queryset, many=True, request=request)
|
||||
return SuccessResponse(data=serializer.data, msg="获取成功")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def get_newest_msg(self, request):
|
||||
"""
|
||||
获取最新的一条消息
|
||||
"""
|
||||
self_user_id = self.request.user.id
|
||||
queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('create_datetime').last()
|
||||
data = None
|
||||
if queryset:
|
||||
serializer = MessageCenterTargetUserListSerializer(queryset.messagecenter, many=False, request=request)
|
||||
data = serializer.data
|
||||
return DetailResponse(data=data, msg="获取成功")
|
||||
47
backend/dvadmin/system/views/operation_log.py
Normal file
47
backend/dvadmin/system/views/operation_log.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 李强
|
||||
@contact: QQ:1206709430
|
||||
@Created on: 2021/6/8 003 0:30
|
||||
@Remark: 操作日志管理
|
||||
"""
|
||||
|
||||
from dvadmin.system.models import OperationLog
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class OperationLogSerializer(CustomModelSerializer):
|
||||
"""
|
||||
日志-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = OperationLog
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class OperationLogCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
操作日志 创建/更新时的列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = OperationLog
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class OperationLogViewSet(CustomModelViewSet):
|
||||
"""
|
||||
操作日志接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = OperationLog.objects.order_by('-create_datetime')
|
||||
serializer_class = OperationLogSerializer
|
||||
# permission_classes = []
|
||||
98
backend/dvadmin/system/views/role.py
Normal file
98
backend/dvadmin/system/views/role.py
Normal file
@@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2021/6/3 003 0:30
|
||||
@Remark: 角色管理
|
||||
"""
|
||||
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.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.json_response import SuccessResponse, DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.validator import CustomUniqueValidator
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class RoleSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class RoleCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
角色管理 创建/更新时的列化器
|
||||
"""
|
||||
menu = MenuSerializer(many=True, read_only=True)
|
||||
dept = DeptSerializer(many=True, read_only=True)
|
||||
permission = MenuButtonSerializer(many=True, read_only=True)
|
||||
key = serializers.CharField(max_length=50,
|
||||
validators=[CustomUniqueValidator(queryset=Role.objects.all(), message="权限字符必须唯一")])
|
||||
name = serializers.CharField(max_length=50, validators=[CustomUniqueValidator(queryset=Role.objects.all())])
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
return super().validate(attrs)
|
||||
|
||||
def save(self, **kwargs):
|
||||
is_superuser = self.request.user.is_superuser
|
||||
if not is_superuser:
|
||||
self.validated_data.pop('admin')
|
||||
data = super().save(**kwargs)
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = Role
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class MenuPermissonSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单的按钮权限
|
||||
"""
|
||||
menuPermission = serializers.SerializerMethodField()
|
||||
|
||||
def get_menuPermission(self, instance):
|
||||
is_superuser = self.request.user.is_superuser
|
||||
if is_superuser:
|
||||
queryset = MenuButton.objects.filter(menu__id=instance.id)
|
||||
else:
|
||||
menu_permission_id_list = self.request.user.role.values_list('permission',flat=True)
|
||||
queryset = MenuButton.objects.filter(id__in=menu_permission_id_list,menu__id=instance.id)
|
||||
serializer = MenuButtonSerializer(queryset,many=True, read_only=True)
|
||||
return serializer.data
|
||||
|
||||
class Meta:
|
||||
model = Menu
|
||||
fields = ['id', 'parent', 'name', 'menuPermission']
|
||||
|
||||
|
||||
class RoleViewSet(CustomModelViewSet,FastCrudMixin):
|
||||
"""
|
||||
角色管理接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = Role.objects.all()
|
||||
serializer_class = RoleSerializer
|
||||
create_serializer_class = RoleCreateUpdateSerializer
|
||||
update_serializer_class = RoleCreateUpdateSerializer
|
||||
search_fields = ['name', 'key']
|
||||
86
backend/dvadmin/system/views/role_menu.py
Normal file
86
backend/dvadmin/system/views/role_menu.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db.models import F
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from dvadmin.system.models import RoleMenuPermission, Menu, MenuButton
|
||||
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class RoleMenuPermissionSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuPermission
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class RoleMenuPermissionInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuPermission
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
class RoleMenuPermissionCreateUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuPermission
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class RoleMenuPermissionViewSet(CustomModelViewSet):
|
||||
"""
|
||||
菜单按钮接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = RoleMenuPermission.objects.all()
|
||||
serializer_class = RoleMenuPermissionSerializer
|
||||
create_serializer_class = RoleMenuPermissionCreateUpdateSerializer
|
||||
update_serializer_class = RoleMenuPermissionCreateUpdateSerializer
|
||||
extra_filter_class = []
|
||||
|
||||
@action(methods=['post'],detail=False)
|
||||
def save_auth(self,request):
|
||||
"""
|
||||
保存页面菜单授权
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
body = request.data
|
||||
role_id = body.get('role',None)
|
||||
if role_id is None:
|
||||
return ErrorResponse(msg="未获取到角色参数")
|
||||
menu_list = body.get('menu',None)
|
||||
if menu_list is None:
|
||||
return ErrorResponse(msg="未获取到菜单参数")
|
||||
obj_list = RoleMenuPermission.objects.filter(role__id=role_id).values_list('menu__id',flat=True)
|
||||
old_set = set(obj_list)
|
||||
new_set = set(menu_list)
|
||||
#need_update = old_set.intersection(new_set) # 需要更新的
|
||||
need_del = old_set.difference(new_set) # 需要删除的
|
||||
need_add = new_set.difference(old_set) # 需要新增的
|
||||
RoleMenuPermission.objects.filter(role__id=role_id,menu__in=list(need_del)).delete()
|
||||
data = [{"role": role_id, "menu": item} for item in list(need_add)]
|
||||
serializer = RoleMenuPermissionSerializer(data=data,many=True,request=request)
|
||||
if serializer.is_valid(raise_exception=True):
|
||||
serializer.save()
|
||||
return DetailResponse(msg="保存成功",data=serializer.data)
|
||||
280
backend/dvadmin/system/views/role_menu_button_permission.py
Normal file
280
backend/dvadmin/system/views/role_menu_button_permission.py
Normal file
@@ -0,0 +1,280 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2021/6/3 003 0:30
|
||||
@Remark: 菜单按钮管理
|
||||
"""
|
||||
from django.db.models import F, Subquery, OuterRef, Exists
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission
|
||||
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
|
||||
"""
|
||||
菜单按钮-序列化器
|
||||
"""
|
||||
class Meta:
|
||||
model = RoleMenuButtonPermission
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class RoleMenuButtonPermissionInitSerializer(CustomModelSerializer):
|
||||
"""
|
||||
初始化菜单按钮-序列化器
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuButtonPermission
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
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)
|
||||
|
||||
class Meta:
|
||||
model = RoleMenuButtonPermission
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
||||
"""
|
||||
菜单按钮接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
queryset = RoleMenuButtonPermission.objects.all()
|
||||
serializer_class = RoleMenuButtonPermissionSerializer
|
||||
create_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
|
||||
update_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
|
||||
extra_filter_class = []
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def role_get_menu(self, request):
|
||||
"""根据当前用户的角色返回角色拥有的菜单"""
|
||||
data = []
|
||||
is_superuser = request.user.is_superuser
|
||||
is_admin = request.user.role.values_list('admin', flat=True)
|
||||
if is_superuser or True in is_admin:
|
||||
queryset = Menu.objects.filter(status=1).values('name','parent','is_catalog',menu_id=F('id'))
|
||||
for item in queryset:
|
||||
btn_name = MenuButton.objects.filter(menu=item['menu_id']).values_list(
|
||||
'name', flat=True)
|
||||
data.append({'menu_id': item['menu_id'], 'name': item['name'], 'parent': item['parent'],
|
||||
'permission': ','.join(btn_name), 'is_catalog': item['is_catalog']})
|
||||
else:
|
||||
role_id = request.user.role.values_list('id',flat=True)
|
||||
queryset = RoleMenuPermission.objects.filter(role__in=role_id).values('menu_id',name=F('menu__name'),parent=F('menu__parent'),is_catalog=F('menu__is_catalog')).distinct()
|
||||
for item in queryset:
|
||||
btn_name = RoleMenuButtonPermission.objects.filter(menu_button__menu=item['menu_id']).values_list('menu_button__name',flat=True)
|
||||
data.append({'menu_id':item['menu_id'], 'name':item['name'], 'parent':item['parent'],'permission':','.join(btn_name),'is_catalog':item['is_catalog']})
|
||||
return DetailResponse(data=data)
|
||||
|
||||
@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
|
||||
is_admin = request.user.role.values_list('admin', flat=True)
|
||||
if is_superuser or True in is_admin:
|
||||
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="参数错误")
|
||||
|
||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def data_scope(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)
|
||||
else:
|
||||
data = []
|
||||
role_list = request.user.role.values_list('id',flat=True)
|
||||
if params := request.query_params:
|
||||
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)
|
||||
data_range_list = list(set(role_queryset))
|
||||
for item in data_range_list:
|
||||
if item == 0:
|
||||
data = [{
|
||||
"value": 0,
|
||||
"label": '仅本人数据权限'
|
||||
}]
|
||||
elif item == 1:
|
||||
data = [{
|
||||
"value": 0,
|
||||
"label": '仅本人数据权限'
|
||||
}, {
|
||||
"value": 1,
|
||||
"label": '本部门及以下数据权限'
|
||||
},
|
||||
{
|
||||
"value": 2,
|
||||
"label": '本部门数据权限'
|
||||
}]
|
||||
elif item == 2:
|
||||
data = [{
|
||||
"value": 0,
|
||||
"label": '仅本人数据权限'
|
||||
},
|
||||
{
|
||||
"value": 2,
|
||||
"label": '本部门数据权限'
|
||||
}]
|
||||
elif item == 3:
|
||||
data = [{
|
||||
"value": 0,
|
||||
"label": '仅本人数据权限'
|
||||
},
|
||||
{
|
||||
"value": 3,
|
||||
"label": '全部数据权限'
|
||||
}, ]
|
||||
elif item == 4:
|
||||
data = [{
|
||||
"value": 0,
|
||||
"label": '仅本人数据权限'
|
||||
},
|
||||
{
|
||||
"value": 4,
|
||||
"label": '自定义数据权限'
|
||||
}]
|
||||
else:
|
||||
data = []
|
||||
return DetailResponse(data=data)
|
||||
return ErrorResponse(msg="参数错误")
|
||||
|
||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
||||
def role_to_dept_all(self, request):
|
||||
"""
|
||||
当前用户角色下所能授权的部门:角色授权页面使用
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
params = request.query_params
|
||||
is_superuser = request.user.is_superuser
|
||||
is_admin = request.user.role.values_list('admin', flat=True)
|
||||
if is_superuser or True in is_admin:
|
||||
queryset = Dept.objects.values('id','name','parent')
|
||||
else:
|
||||
if not params:
|
||||
return ErrorResponse(msg="参数错误")
|
||||
menu_button = params.get('menu_button')
|
||||
if menu_button is None:
|
||||
return ErrorResponse(msg="参数错误")
|
||||
role_list = request.user.role.values_list('id', flat=True)
|
||||
queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button=None).values(
|
||||
dept_id=F('dept__id'),
|
||||
name=F('dept__name'),
|
||||
parent=F('dept__parent')
|
||||
)
|
||||
return DetailResponse(data=queryset)
|
||||
|
||||
|
||||
|
||||
@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
|
||||
is_admin = request.user.role.values_list('admin', flat=True)
|
||||
if is_superuser or True in is_admin:
|
||||
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)
|
||||
|
||||
234
backend/dvadmin/system/views/system_config.py
Normal file
234
backend/dvadmin/system/views/system_config.py
Normal file
@@ -0,0 +1,234 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
@author: 猿小天
|
||||
@contact: QQ:1638245306
|
||||
@Created on: 2022/1/21 003 0:30
|
||||
@Remark: 系统配置
|
||||
"""
|
||||
import django_filters
|
||||
from django.db.models import Q
|
||||
from django_filters.rest_framework import BooleanFilter
|
||||
from rest_framework import serializers
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from application import dispatch
|
||||
from dvadmin.system.models import SystemConfig
|
||||
from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
|
||||
from dvadmin.utils.models import get_all_models_objects
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.validator import CustomValidationError
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
class SystemConfigCreateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
系统配置-新增时使用-序列化器
|
||||
"""
|
||||
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = SystemConfig
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
def validate_key(self, value):
|
||||
"""
|
||||
验证key是否允许重复
|
||||
parent为空时不允许重复,反之允许
|
||||
"""
|
||||
instance = SystemConfig.objects.filter(key=value, parent__isnull=True).exists()
|
||||
if instance:
|
||||
raise CustomValidationError('已存在相同变量名')
|
||||
return value
|
||||
|
||||
|
||||
|
||||
|
||||
class SystemConfigSerializer(CustomModelSerializer):
|
||||
"""
|
||||
系统配置-序列化器
|
||||
"""
|
||||
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = SystemConfig
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class SystemConfigChinldernSerializer(CustomModelSerializer):
|
||||
"""
|
||||
系统配置子级-序列化器
|
||||
"""
|
||||
children = serializers.SerializerMethodField()
|
||||
form_item_type_label = serializers.CharField(source='get_form_item_type_display', read_only=True)
|
||||
|
||||
def get_children(self, instance):
|
||||
queryset = SystemConfig.objects.filter(parent=instance)
|
||||
serializer = SystemConfigSerializer(queryset, many=True)
|
||||
return serializer.data
|
||||
|
||||
class Meta:
|
||||
model = SystemConfig
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class SystemConfigListSerializer(CustomModelSerializer):
|
||||
"""
|
||||
系统配置下模块的保存-序列化器
|
||||
"""
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
instance_mapping = {obj.id: obj for obj in instance}
|
||||
data_mapping = {item['id']: item for item in validated_data}
|
||||
for obj_id, data in data_mapping.items():
|
||||
instance_obj = instance_mapping.get(obj_id, None)
|
||||
if instance_obj is None:
|
||||
return SystemConfig.objects.create(**data)
|
||||
else:
|
||||
return instance_obj.objects.update(**data)
|
||||
|
||||
class Meta:
|
||||
model = SystemConfig
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class SystemConfigSaveSerializer(serializers.Serializer):
|
||||
class Meta:
|
||||
read_only_fields = ["id"]
|
||||
list_serializer_class = SystemConfigListSerializer
|
||||
|
||||
|
||||
class SystemConfigFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
过滤器
|
||||
"""
|
||||
parent__isnull = BooleanFilter(field_name='parent', lookup_expr="isnull")
|
||||
|
||||
class Meta:
|
||||
model = SystemConfig
|
||||
fields = ['id', 'parent', 'status', 'parent__isnull']
|
||||
|
||||
|
||||
class SystemConfigViewSet(CustomModelViewSet):
|
||||
"""
|
||||
系统配置接口
|
||||
"""
|
||||
queryset = SystemConfig.objects.order_by('sort', 'create_datetime')
|
||||
serializer_class = SystemConfigChinldernSerializer
|
||||
create_serializer_class = SystemConfigCreateSerializer
|
||||
retrieve_serializer_class = SystemConfigChinldernSerializer
|
||||
# filter_fields = ['id','parent']
|
||||
filter_class = SystemConfigFilter
|
||||
|
||||
def save_content(self, request):
|
||||
body = request.data
|
||||
data_mapping = {item['id']: item for item in body}
|
||||
for obj_id, data in data_mapping.items():
|
||||
instance_obj = SystemConfig.objects.filter(id=obj_id).first()
|
||||
if instance_obj is None:
|
||||
# return SystemConfig.objects.create(**data)
|
||||
serializer = SystemConfigCreateSerializer(data=data)
|
||||
else:
|
||||
serializer = SystemConfigCreateSerializer(instance_obj, data=data)
|
||||
if serializer.is_valid(raise_exception=True):
|
||||
serializer.save()
|
||||
return DetailResponse(msg="保存成功")
|
||||
|
||||
def get_association_table(self, request):
|
||||
"""
|
||||
获取所有的model及字段信息
|
||||
"""
|
||||
res = [ele.get('table') for ele in get_all_models_objects().values()]
|
||||
return DetailResponse(msg="获取成功", data=res)
|
||||
|
||||
def get_table_data(self, request, pk):
|
||||
"""
|
||||
动态获取关联表的数据
|
||||
"""
|
||||
instance = SystemConfig.objects.filter(id=pk).first()
|
||||
if instance is None:
|
||||
return ErrorResponse(msg="查询出错了~")
|
||||
setting = instance.setting
|
||||
if setting is None:
|
||||
return ErrorResponse(msg="查询出错了~")
|
||||
table = setting.get('table') # 获取model名
|
||||
model = get_all_models_objects(table).get("object", {})
|
||||
# 自己判断一下不存在
|
||||
queryset = model.objects.values()
|
||||
body = request.query_params
|
||||
search_value = body.get('search', None)
|
||||
if search_value:
|
||||
search_fields = setting.get('searchField')
|
||||
filters = Q()
|
||||
filters.connector = 'OR'
|
||||
for item in search_fields:
|
||||
filed = '{0}__icontains'.format(item.get('field'))
|
||||
filters.children.append((filed, search_value))
|
||||
queryset = model.objects.filter(filters).values()
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
return self.get_paginated_response(queryset)
|
||||
return SuccessResponse(msg="获取成功", data=queryset, total=len(queryset))
|
||||
|
||||
def get_relation_info(self, request):
|
||||
"""
|
||||
查询关联的模板信息
|
||||
"""
|
||||
body = request.query_params
|
||||
var_name = body.get('varName', None)
|
||||
table = body.get('table', None)
|
||||
instance = SystemConfig.objects.filter(key=var_name, setting__table=table).first()
|
||||
if instance is None:
|
||||
return ErrorResponse(msg="未获取到关联信息")
|
||||
relation_id = body.get('relationIds', None)
|
||||
relationIds = []
|
||||
if relation_id is None:
|
||||
return ErrorResponse(msg="未获取到关联信息")
|
||||
if instance.form_item_type in [13]:
|
||||
relationIds = [relation_id]
|
||||
elif instance.form_item_type in [14]:
|
||||
relationIds = relation_id.split(',')
|
||||
queryset = SystemConfig.objects.filter(value__in=relationIds).first()
|
||||
if queryset is None:
|
||||
return ErrorResponse(msg="未获取到关联信息")
|
||||
serializer = SystemConfigChinldernSerializer(queryset.parent)
|
||||
return DetailResponse(msg="查询成功", data=serializer.data)
|
||||
|
||||
|
||||
class InitSettingsViewSet(APIView):
|
||||
"""
|
||||
获取初始化配置
|
||||
"""
|
||||
authentication_classes = []
|
||||
permission_classes = []
|
||||
|
||||
def filter_system_config_values(self, data: dict):
|
||||
"""
|
||||
过滤系统初始化配置
|
||||
:param data:
|
||||
:return:
|
||||
"""
|
||||
if not self.request.query_params.get('key', ''):
|
||||
return data
|
||||
new_data = {}
|
||||
for key in self.request.query_params.get('key', '').split('|'):
|
||||
if key:
|
||||
new_data.update(**dict(filter(lambda x: x[0].startswith(key), data.items())))
|
||||
return new_data
|
||||
|
||||
def get(self, request):
|
||||
data = dispatch.get_system_config()
|
||||
if not data:
|
||||
dispatch.refresh_system_config()
|
||||
data = dispatch.get_system_config()
|
||||
# 不返回后端专用配置
|
||||
backend_config = [f"{ele.get('parent__key')}.{ele.get('key')}" for ele in
|
||||
SystemConfig.objects.filter(status=False, parent_id__isnull=False).values('parent__key',
|
||||
'key')]
|
||||
data = dict(filter(lambda x: x[0] not in backend_config, data.items()))
|
||||
data = self.filter_system_config_values(data=data)
|
||||
return DetailResponse(data=data)
|
||||
365
backend/dvadmin/system/views/user.py
Normal file
365
backend/dvadmin/system/views/user.py
Normal file
@@ -0,0 +1,365 @@
|
||||
import hashlib
|
||||
|
||||
from django.contrib.auth.hashers import make_password, check_password
|
||||
from django_restql.fields import DynamicSerializerMethodField
|
||||
from rest_framework import serializers
|
||||
from rest_framework.decorators import action, permission_classes
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from django.db import connection
|
||||
from application import dispatch
|
||||
from dvadmin.system.models import Users, Role, Dept
|
||||
from dvadmin.system.views.role import RoleSerializer
|
||||
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
from dvadmin.utils.validator import CustomUniqueValidator
|
||||
from dvadmin.utils.viewset import CustomModelViewSet
|
||||
|
||||
|
||||
def recursion(instance, parent, result):
|
||||
new_instance = getattr(instance, parent, None)
|
||||
res = []
|
||||
data = getattr(instance, result, None)
|
||||
if data:
|
||||
res.append(data)
|
||||
if new_instance:
|
||||
array = recursion(new_instance, parent, result)
|
||||
res += (array)
|
||||
return res
|
||||
|
||||
|
||||
class UserSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户管理-序列化器
|
||||
"""
|
||||
dept_name = serializers.CharField(source='dept.name', read_only=True)
|
||||
role_info = DynamicSerializerMethodField()
|
||||
dept_name_all = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
read_only_fields = ["id"]
|
||||
exclude = ["password"]
|
||||
extra_kwargs = {
|
||||
"post": {"required": False},
|
||||
"mobile": {"required": False},
|
||||
}
|
||||
|
||||
def get_dept_name_all(self, instance):
|
||||
dept_name_all = recursion(instance.dept, "parent", "name")
|
||||
dept_name_all.reverse()
|
||||
return "/".join(dept_name_all)
|
||||
|
||||
def get_role_info(self, instance, parsed_query):
|
||||
roles = instance.role.all()
|
||||
# You can do what ever you want in here
|
||||
# `parsed_query` param is passed to BookSerializer to allow further querying
|
||||
serializer = RoleSerializer(
|
||||
roles,
|
||||
many=True,
|
||||
parsed_query=parsed_query
|
||||
)
|
||||
return serializer.data
|
||||
|
||||
|
||||
class UserCreateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户新增-序列化器
|
||||
"""
|
||||
|
||||
username = serializers.CharField(
|
||||
max_length=50,
|
||||
validators=[
|
||||
CustomUniqueValidator(queryset=Users.objects.all(), message="账号必须唯一")
|
||||
],
|
||||
)
|
||||
password = serializers.CharField(
|
||||
required=False,
|
||||
)
|
||||
|
||||
def validate_password(self, value):
|
||||
"""
|
||||
对密码进行验证
|
||||
"""
|
||||
md5 = hashlib.md5()
|
||||
md5.update(value.encode('utf-8'))
|
||||
md5_password = md5.hexdigest()
|
||||
return make_password(md5_password)
|
||||
|
||||
def save(self, **kwargs):
|
||||
data = super().save(**kwargs)
|
||||
data.dept_belong_id = data.dept_id
|
||||
data.save()
|
||||
data.post.set(self.initial_data.get("post", []))
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
fields = "__all__"
|
||||
read_only_fields = ["id"]
|
||||
extra_kwargs = {
|
||||
"post": {"required": False},
|
||||
"mobile": {"required": False},
|
||||
}
|
||||
|
||||
|
||||
class UserUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户修改-序列化器
|
||||
"""
|
||||
|
||||
username = serializers.CharField(
|
||||
max_length=50,
|
||||
validators=[
|
||||
CustomUniqueValidator(queryset=Users.objects.all(), message="账号必须唯一")
|
||||
],
|
||||
)
|
||||
|
||||
# password = serializers.CharField(required=False, allow_blank=True)
|
||||
# mobile = serializers.CharField(
|
||||
# max_length=50,
|
||||
# validators=[
|
||||
# CustomUniqueValidator(queryset=Users.objects.all(), message="手机号必须唯一")
|
||||
# ],
|
||||
# allow_blank=True
|
||||
# )
|
||||
|
||||
def save(self, **kwargs):
|
||||
data = super().save(**kwargs)
|
||||
data.dept_belong_id = data.dept_id
|
||||
data.save()
|
||||
data.post.set(self.initial_data.get("post", []))
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
read_only_fields = ["id", "password"]
|
||||
fields = "__all__"
|
||||
extra_kwargs = {
|
||||
"post": {"required": False, "read_only": True},
|
||||
"mobile": {"required": False},
|
||||
}
|
||||
|
||||
|
||||
class UserInfoUpdateSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户修改-序列化器
|
||||
"""
|
||||
mobile = serializers.CharField(
|
||||
max_length=50,
|
||||
validators=[
|
||||
CustomUniqueValidator(queryset=Users.objects.all(), message="手机号必须唯一")
|
||||
],
|
||||
allow_blank=True
|
||||
)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
fields = ['email', 'mobile', 'avatar', 'name', 'gender']
|
||||
extra_kwargs = {
|
||||
"post": {"required": False, "read_only": True},
|
||||
"mobile": {"required": False},
|
||||
}
|
||||
|
||||
|
||||
class ExportUserProfileSerializer(CustomModelSerializer):
|
||||
"""
|
||||
用户导出 序列化器
|
||||
"""
|
||||
|
||||
last_login = serializers.DateTimeField(
|
||||
format="%Y-%m-%d %H:%M:%S", required=False, read_only=True
|
||||
)
|
||||
is_active = serializers.SerializerMethodField(read_only=True)
|
||||
dept_name = serializers.CharField(source="dept.name", default="")
|
||||
dept_owner = serializers.CharField(source="dept.owner", default="")
|
||||
gender = serializers.CharField(source="get_gender_display", read_only=True)
|
||||
|
||||
def get_is_active(self, instance):
|
||||
return "启用" if instance.is_active else "停用"
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
fields = (
|
||||
"username",
|
||||
"name",
|
||||
"email",
|
||||
"mobile",
|
||||
"gender",
|
||||
"is_active",
|
||||
"last_login",
|
||||
"dept_name",
|
||||
"dept_owner",
|
||||
)
|
||||
|
||||
|
||||
class UserProfileImportSerializer(CustomModelSerializer):
|
||||
password = serializers.CharField(read_only=True, required=False)
|
||||
def save(self, **kwargs):
|
||||
data = super().save(**kwargs)
|
||||
password = hashlib.new(
|
||||
"md5", str(self.initial_data.get("password", "admin123456")).encode(encoding="UTF-8")
|
||||
).hexdigest()
|
||||
data.set_password(password)
|
||||
data.save()
|
||||
return data
|
||||
|
||||
class Meta:
|
||||
model = Users
|
||||
exclude = (
|
||||
"post",
|
||||
"user_permissions",
|
||||
"groups",
|
||||
"is_superuser",
|
||||
"date_joined",
|
||||
)
|
||||
|
||||
|
||||
class UserViewSet(CustomModelViewSet):
|
||||
"""
|
||||
用户接口
|
||||
list:查询
|
||||
create:新增
|
||||
update:修改
|
||||
retrieve:单例
|
||||
destroy:删除
|
||||
"""
|
||||
|
||||
queryset = Users.objects.exclude(is_superuser=1).all()
|
||||
serializer_class = UserSerializer
|
||||
create_serializer_class = UserCreateSerializer
|
||||
update_serializer_class = UserUpdateSerializer
|
||||
filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"]
|
||||
search_fields = ["username", "name", "gender", "dept__name", "role__name"]
|
||||
# 导出
|
||||
export_field_label = {
|
||||
"username": "用户账号",
|
||||
"name": "用户名称",
|
||||
"email": "用户邮箱",
|
||||
"mobile": "手机号码",
|
||||
"gender": "用户性别",
|
||||
"is_active": "帐号状态",
|
||||
"last_login": "最后登录时间",
|
||||
"dept_name": "部门名称",
|
||||
"dept_owner": "部门负责人",
|
||||
}
|
||||
export_serializer_class = ExportUserProfileSerializer
|
||||
# 导入
|
||||
import_serializer_class = UserProfileImportSerializer
|
||||
import_field_dict = {
|
||||
"username": "登录账号",
|
||||
"name": "用户名称",
|
||||
"email": "用户邮箱",
|
||||
"mobile": "手机号码",
|
||||
"gender": {
|
||||
"title": "用户性别",
|
||||
"choices": {
|
||||
"data": {"未知": 2, "男": 1, "女": 0},
|
||||
}
|
||||
},
|
||||
"is_active": {
|
||||
"title": "帐号状态",
|
||||
"choices": {
|
||||
"data": {"启用": True, "禁用": False},
|
||||
}
|
||||
},
|
||||
"dept": {"title": "部门", "choices": {"queryset": Dept.objects.filter(status=True), "values_name": "name"}},
|
||||
"role": {"title": "角色", "choices": {"queryset": Role.objects.filter(status=True), "values_name": "name"}},
|
||||
}
|
||||
|
||||
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated])
|
||||
def user_info(self, request):
|
||||
"""获取当前用户信息"""
|
||||
user = request.user
|
||||
result = {
|
||||
"id": user.id,
|
||||
"username": user.username,
|
||||
"name": user.name,
|
||||
"mobile": user.mobile,
|
||||
"user_type": user.user_type,
|
||||
"gender": user.gender,
|
||||
"email": user.email,
|
||||
"avatar": user.avatar,
|
||||
"dept": user.dept_id,
|
||||
"is_superuser": user.is_superuser,
|
||||
"role": user.role.values_list('id', flat=True),
|
||||
}
|
||||
if hasattr(connection, 'tenant'):
|
||||
result['tenant_id'] = connection.tenant and connection.tenant.id
|
||||
result['tenant_name'] = connection.tenant and connection.tenant.name
|
||||
dept = getattr(user, 'dept', None)
|
||||
if dept:
|
||||
result['dept_info'] = {
|
||||
'dept_id': dept.id,
|
||||
'dept_name': dept.name
|
||||
}
|
||||
else:
|
||||
result['dept_info'] = {
|
||||
'dept_id': None,
|
||||
'dept_name': "暂无部门"
|
||||
}
|
||||
role = getattr(user, 'role', None)
|
||||
if role:
|
||||
result['role_info'] = role.values('id', 'name', 'key')
|
||||
return DetailResponse(data=result, msg="获取成功")
|
||||
|
||||
@action(methods=["PUT"], detail=False, permission_classes=[IsAuthenticated])
|
||||
def update_user_info(self, request):
|
||||
"""修改当前用户信息"""
|
||||
serializer = UserInfoUpdateSerializer(request.user, data=request.data, request=request)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return DetailResponse(data=None, msg="修改成功")
|
||||
|
||||
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
|
||||
def change_password(self, request, *args, **kwargs):
|
||||
"""密码修改"""
|
||||
data = request.data
|
||||
old_pwd = data.get("oldPassword")
|
||||
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:
|
||||
return ErrorResponse(msg="参数不能为空")
|
||||
if new_pwd != new_pwd2:
|
||||
return ErrorResponse(msg="两次密码不匹配")
|
||||
verify_password = check_password(old_pwd, self.request.user.password)
|
||||
if not verify_password:
|
||||
verify_password = check_password(hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest(), self.request.user.password)
|
||||
if verify_password:
|
||||
request.user.password = make_password(new_pwd)
|
||||
request.user.save()
|
||||
return DetailResponse(data=None, msg="修改成功")
|
||||
else:
|
||||
return ErrorResponse(msg="旧密码不正确")
|
||||
|
||||
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
|
||||
def reset_to_default_password(self, request, *args, **kwargs):
|
||||
"""恢复默认密码"""
|
||||
instance = Users.objects.filter(id=kwargs.get("pk")).first()
|
||||
if instance:
|
||||
instance.set_password(dispatch.get_system_config_values("base.default_password"))
|
||||
instance.save()
|
||||
return DetailResponse(data=None, msg="密码重置成功")
|
||||
else:
|
||||
return ErrorResponse(msg="未获取到用户")
|
||||
|
||||
@action(methods=["PUT"], detail=True)
|
||||
def reset_password(self, request, pk):
|
||||
"""
|
||||
密码重置
|
||||
"""
|
||||
instance = Users.objects.filter(id=pk).first()
|
||||
data = request.data
|
||||
new_pwd = data.get("newPassword")
|
||||
new_pwd2 = data.get("newPassword2")
|
||||
if instance:
|
||||
if new_pwd != new_pwd2:
|
||||
return ErrorResponse(msg="两次密码不匹配")
|
||||
else:
|
||||
instance.password = make_password(new_pwd)
|
||||
instance.save()
|
||||
return DetailResponse(data=None, msg="修改成功")
|
||||
else:
|
||||
return ErrorResponse(msg="未获取到用户")
|
||||
Reference in New Issue
Block a user