Merge branch 'dvadmin-liqianglog' of https://gitee.com/liqianglog/django-vue-admin into dvadmin-xt12321

pull/19/head
xt12321 2021-04-24 11:15:20 +08:00
commit 5a22acd21d
17 changed files with 131 additions and 43 deletions

View File

@ -8,6 +8,8 @@ version: "3"
services: services:
dvadmin-ui: dvadmin-ui:
container_name: dvadmin-ui container_name: dvadmin-ui
ports:
- "8080:8080"
build: build:
context: ./ context: ./
dockerfile: ./docker_env/vue-ui/Dockerfile dockerfile: ./docker_env/vue-ui/Dockerfile

View File

@ -9,7 +9,7 @@ class Monitor(CoreModel):
mem_num = CharField(max_length=32, verbose_name='内存总数(KB)') mem_num = CharField(max_length=32, verbose_name='内存总数(KB)')
mem_sys = CharField(max_length=32, verbose_name='内存已使用大小(KB)') mem_sys = CharField(max_length=32, verbose_name='内存已使用大小(KB)')
seconds = CharField(max_length=32, verbose_name='系统已运行时间') seconds = CharField(max_length=32, verbose_name='系统已运行时间')
server = ForeignKey(to='Server', on_delete=CASCADE, verbose_name="关联服务器信息", db_constraint=False) server = ForeignKey(to='monitor.Server', on_delete=CASCADE, verbose_name="关联服务器信息", db_constraint=False)
class Meta: class Meta:
verbose_name = '服务器监控信息' verbose_name = '服务器监控信息'

View File

@ -9,7 +9,7 @@ class SysFiles(CoreModel):
type_name = CharField(max_length=32, verbose_name='盘符类型') type_name = CharField(max_length=32, verbose_name='盘符类型')
total = CharField(max_length=32, verbose_name='磁盘总大小(KB)') total = CharField(max_length=32, verbose_name='磁盘总大小(KB)')
disk_sys = CharField(max_length=32, verbose_name='已使用大小(KB)') disk_sys = CharField(max_length=32, verbose_name='已使用大小(KB)')
monitor = ForeignKey(to='Monitor', on_delete=CASCADE, verbose_name="关联服务器监控信息", db_constraint=False) monitor = ForeignKey(to='monitor.Monitor', on_delete=CASCADE, verbose_name="关联服务器监控信息", db_constraint=False)
class Meta: class Meta:
verbose_name = '系统磁盘' verbose_name = '系统磁盘'

View File

@ -13,7 +13,18 @@ class ServerSerializer(CustomModelSerializer):
class Meta: class Meta:
model = Server model = Server
fields = '__all__' fields = ("id", "ip", "name", "os", "remark")
class UpdateServerSerializer(CustomModelSerializer):
"""
服务器信息 简单序列化器
"""
class Meta:
model = Server
fields = ("name", "remark")
# ================================================= # # ================================================= #
# ************** 服务器监控信息 序列化器 ************** # # ************** 服务器监控信息 序列化器 ************** #

View File

@ -8,7 +8,8 @@ router.register(r'server', ServerModelViewSet)
router.register(r'monitor', MonitorModelViewSet) router.register(r'monitor', MonitorModelViewSet)
urlpatterns = [ urlpatterns = [
re_path('monitor/info/', MonitorModelViewSet.as_view({'get': 'get_monitor_info'})), re_path('monitor/info/(?P<pk>.*)/', MonitorModelViewSet.as_view({'get': 'get_monitor_info'})),
re_path('monitor/rate/(?P<pk>.*)/', MonitorModelViewSet.as_view({'get': 'get_rate_info'})),
re_path('monitor/enabled/', MonitorModelViewSet.as_view({'get': 'enabled_monitor_info'})), re_path('monitor/enabled/', MonitorModelViewSet.as_view({'get': 'enabled_monitor_info'})),
re_path('monitor/clean/', MonitorModelViewSet.as_view({'get': 'clean_all'})), re_path('monitor/clean/', MonitorModelViewSet.as_view({'get': 'clean_all'})),
] ]

View File

@ -2,9 +2,9 @@ from django_celery_beat.models import PeriodicTask, IntervalSchedule, CrontabSch
from rest_framework.request import Request from rest_framework.request import Request
from .filters import ServerFilter, MonitorFilter from .filters import ServerFilter, MonitorFilter
from .models import Server, Monitor from .models import Server, Monitor, SysFiles
from .serializers import ServerSerializer, MonitorSerializer from .serializers import ServerSerializer, MonitorSerializer, UpdateServerSerializer
from ..op_drf.response import SuccessResponse from ..op_drf.response import SuccessResponse, ErrorResponse
from ..op_drf.viewsets import CustomModelViewSet from ..op_drf.viewsets import CustomModelViewSet
from ..permission.permissions import CommonPermission from ..permission.permissions import CommonPermission
from ..system.models import ConfigSettings from ..system.models import ConfigSettings
@ -16,6 +16,7 @@ class ServerModelViewSet(CustomModelViewSet):
""" """
queryset = Server.objects.all() queryset = Server.objects.all()
serializer_class = ServerSerializer serializer_class = ServerSerializer
update_serializer_class = UpdateServerSerializer
# extra_filter_backends = [DataLevelPermissionsFilter] # extra_filter_backends = [DataLevelPermissionsFilter]
filter_class = ServerFilter filter_class = ServerFilter
update_extra_permission_classes = (CommonPermission,) update_extra_permission_classes = (CommonPermission,)
@ -37,7 +38,80 @@ class MonitorModelViewSet(CustomModelViewSet):
create_extra_permission_classes = (CommonPermission,) create_extra_permission_classes = (CommonPermission,)
ordering = '-create_datetime' # 默认排序 ordering = '-create_datetime' # 默认排序
def get_rate_info(self, request: Request, *args, **kwargs):
"""
获取使用率 监控信息
:param request:
:param args:
:param kwargs:
:return:
"""
pk = kwargs.get("pk")
queryset = self.filter_queryset(self.get_queryset())
queryset = queryset.filter(server__id=pk).order_by("-create_datetime")
# 间隔取值
queryset_count = queryset.count()
Interval_num = 1 if queryset_count < 200 else int(queryset_count / 100)
queryset = queryset.values('cpu_sys', 'mem_num', 'mem_sys')[::Interval_num][:100]
data = {
"cpu": [],
"memory": [],
}
for ele in queryset:
data["cpu"].append(float(ele.get('cpu_sys', 0)))
data["memory"].append(float(ele.get('mem_num', 0)) and round(float(ele.get('mem_sys', 0)) /
float(ele.get('mem_num', 0)), 4))
return SuccessResponse(data=data)
def get_monitor_info(self, request: Request, *args, **kwargs): def get_monitor_info(self, request: Request, *args, **kwargs):
"""
最新的服务器状态信息
:param request:
:param args:
:param kwargs:
:return:
"""
pk = kwargs.get("pk")
instance = Monitor.objects.filter(server__id=pk).order_by("-create_datetime").first()
if not instance:
return ErrorResponse(msg="未找到服务器信息id")
serializer = self.get_serializer(instance)
data = serializer.data
return SuccessResponse(data={
"cpu": {
"total": int(data.get('cpu_num'), 0),
"used": "", # cpu核心 可不传如指cpu当前主频该值可以传
"rate": float(data.get('cpu_sys', 0)),
"unit": "核心", # 默认单位 核心
},
"memory": {
"total": int(int(data.get('mem_num', 0)) / 1024),
"used": int(int(data.get('mem_sys', 0)) / 1024),
"rate": int(data.get('mem_num', 0)) and round(int(data.get('mem_sys', 0)) /
int(data.get('mem_num', 0)), 4),
"unit": "MB", # 默认单位 MB
},
"disk": [{
"dir_name": ele.get('dir_name'),
"total": int(int(ele.get('total', 0)) / 1024 / 1024 / 1024),
"used": int(int(ele.get('disk_sys', 0)) / 1024 / 1024 / 1024),
"rate": int(ele.get('total', 0)) and round(int(ele.get('disk_sys', 0)) / int(ele.get('total', 0)),
4),
"unit": "GB", # 默认单位 GB
} for ele in SysFiles.objects.filter(monitor=instance).values('dir_name', 'total', 'disk_sys')]
})
def enabled_monitor_info(self, request: Request, *args, **kwargs):
"""
更新和获取监控信息
:param request:
:param args:
:param kwargs:
:return:
"""
enabled = request.query_params.get('enabled', None)
save_days = request.query_params.get('save_days', None)
interval = request.query_params.get('interval', None)
# 定时获取系统监控信息 # 定时获取系统监控信息
periodictask_obj = PeriodicTask.objects.filter(task='apps.vadmin.monitor.tasks.get_monitor_info').first() periodictask_obj = PeriodicTask.objects.filter(task='apps.vadmin.monitor.tasks.get_monitor_info').first()
if not periodictask_obj: if not periodictask_obj:
@ -73,33 +147,15 @@ class MonitorModelViewSet(CustomModelViewSet):
config_obj.remark = "定时清理多余-系统监控信息默认30天" config_obj.remark = "定时清理多余-系统监控信息默认30天"
config_obj.save() config_obj.save()
# 获取保留天数
return SuccessResponse(data={
"enabled": periodictask_obj.enabled,
"interval": periodictask_obj.interval.every,
"save_days": config_obj.configValue if config_obj else "30",
})
def enabled_monitor_info(self, request: Request, *args, **kwargs):
enabled = request.query_params.get('enabled', None)
save_days = request.query_params.get('save_days', None)
interval = request.query_params.get('interval', None)
periodictask_obj = PeriodicTask.objects.filter(task='apps.vadmin.monitor.tasks.get_monitor_info').first()
if enabled: if enabled:
# 更新监控状态 # 更新监控状态
periodictask_obj.enabled = True if enabled == "1" else False periodictask_obj.enabled = True if enabled == "1" else False
periodictask_obj.save() periodictask_obj.save()
# 更新 定时清理多余 系统监控信息 状态 # 更新 定时清理多余 系统监控信息 状态
clean_task_obj = PeriodicTask.objects.filter(
task='apps.vadmin.monitor.tasks.clean_surplus_monitor_info').first()
clean_task_obj.enabled = True if enabled == "1" else False clean_task_obj.enabled = True if enabled == "1" else False
clean_task_obj.save() clean_task_obj.save()
# 更新保留天数 # 更新保留天数
config_obj = ConfigSettings.objects.filter(configKey='sys.monitor.info.save_days').first()
print(33, save_days)
print(22, config_obj)
if save_days and config_obj: if save_days and config_obj:
config_obj.configValue = save_days config_obj.configValue = save_days
config_obj.save() config_obj.save()

View File

@ -1,3 +1,4 @@
from django.conf import settings
from django.db import models from django.db import models
from django.db.models import SET_NULL from django.db.models import SET_NULL
@ -24,7 +25,7 @@ class CoreModel(models.Model):
增加审计字段, 覆盖字段时, 字段名称请勿修改, 必须统一审计字段名称 增加审计字段, 覆盖字段时, 字段名称请勿修改, 必须统一审计字段名称
""" """
description = DescriptionField() # 描述 description = DescriptionField() # 描述
creator = models.ForeignKey(to='permission.UserProfile', related_query_name='creator_query', null=True, creator = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_query_name='creator_query', null=True,
verbose_name='创建者', on_delete=SET_NULL, db_constraint=False) # 创建者 verbose_name='创建者', on_delete=SET_NULL, db_constraint=False) # 创建者
modifier = ModifierCharField() # 修改者 modifier = ModifierCharField() # 修改者
dept_belong_id = models.CharField(max_length=64, verbose_name="数据归属部门", null=True, blank=True) dept_belong_id = models.CharField(max_length=64, verbose_name="数据归属部门", null=True, blank=True)

View File

@ -1,8 +1,11 @@
import django_filters import django_filters
from django.contrib.auth import get_user_model
from ..permission.models import Menu, Dept, Post, Role, UserProfile from ..permission.models import Menu, Dept, Post, Role
from ..utils.model_util import get_dept from ..utils.model_util import get_dept
UserProfile = get_user_model()
class MenuFilter(django_filters.rest_framework.FilterSet): class MenuFilter(django_filters.rest_framework.FilterSet):
""" """

View File

@ -1,6 +1,7 @@
import logging import logging
import os import os
from django.conf import settings
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection from django.db import connection
@ -75,6 +76,7 @@ class Command(BaseCommand):
parser.add_argument('-N', nargs='*') parser.add_argument('-N', nargs='*')
def handle(self, *args, **options): def handle(self, *args, **options):
user_name = "_".join(settings.AUTH_USER_MODEL.lower().split("."))
init_dict = { init_dict = {
'system_dictdata': [os.path.join('system', 'system_dictdata.sql'), '字典管理', 'system_dictdata'], 'system_dictdata': [os.path.join('system', 'system_dictdata.sql'), '字典管理', 'system_dictdata'],
'system_dictdetails': [os.path.join('system', 'system_dictdetails.sql'), '字典详情', 'system_dictdetails'], 'system_dictdetails': [os.path.join('system', 'system_dictdetails.sql'), '字典详情', 'system_dictdetails'],
@ -86,8 +88,7 @@ class Command(BaseCommand):
'permission_role': [os.path.join('permission', 'permission_role.sql'), '角色管理', 'permission_role': [os.path.join('permission', 'permission_role.sql'), '角色管理',
','.join(['permission_role', 'permission_role_dept', 'permission_role_menu'])], ','.join(['permission_role', 'permission_role_dept', 'permission_role_menu'])],
'permission_userprofile': [os.path.join('permission', 'permission_userprofile.sql'), '用户管理', ','.join( 'permission_userprofile': [os.path.join('permission', 'permission_userprofile.sql'), '用户管理', ','.join(
['permission_userprofile_groups', 'permission_userprofile', 'permission_userprofile_role', [f'{user_name}_groups', f'{user_name}', f'{user_name}_role', f'{user_name}_post'])]
'permission_userprofile_post'])]
} }
init_name = options.get('init_name') init_name = options.get('init_name')
is_yes = None is_yes = None

View File

@ -11,7 +11,7 @@ class Dept(CoreModel):
phone = CharField(max_length=32, verbose_name="联系电话", null=True, blank=True) phone = CharField(max_length=32, verbose_name="联系电话", null=True, blank=True)
email = CharField(max_length=32, verbose_name="邮箱", null=True, blank=True) email = CharField(max_length=32, verbose_name="邮箱", null=True, blank=True)
status = CharField(max_length=8, verbose_name="部门状态", null=True, blank=True) status = CharField(max_length=8, verbose_name="部门状态", null=True, blank=True)
parentId = ForeignKey(to='Dept', on_delete=CASCADE, default=False, verbose_name="上级部门", parentId = ForeignKey(to='permission.Dept', on_delete=CASCADE, default=False, verbose_name="上级部门",
db_constraint=False, null=True, blank=True) db_constraint=False, null=True, blank=True)
class Meta: class Meta:

View File

@ -18,8 +18,8 @@ class Role(CoreModel):
admin = BooleanField(default=False, verbose_name="是否为admin") admin = BooleanField(default=False, verbose_name="是否为admin")
dataScope = CharField(max_length=8,default='1', choices=DATASCOPE_CHOICES, verbose_name="权限范围",) dataScope = CharField(max_length=8,default='1', choices=DATASCOPE_CHOICES, verbose_name="权限范围",)
remark = TextField(verbose_name="备注", help_text="备注", null=True, blank=True) remark = TextField(verbose_name="备注", help_text="备注", null=True, blank=True)
dept = ManyToManyField(to='Dept', verbose_name='数据权限-关联部门', db_constraint=False) dept = ManyToManyField(to='permission.Dept', verbose_name='数据权限-关联部门', db_constraint=False)
menu = ManyToManyField(to='Menu', verbose_name='关联菜单权限', db_constraint=False) menu = ManyToManyField(to='permission.Menu', verbose_name='关联菜单权限', db_constraint=False)
class Meta: class Meta:
verbose_name = '角色管理' verbose_name = '角色管理'

View File

@ -1,5 +1,6 @@
from uuid import uuid4 from uuid import uuid4
from django.conf import settings
from django.contrib.auth.models import UserManager, AbstractUser from django.contrib.auth.models import UserManager, AbstractUser
from django.core.cache import cache from django.core.cache import cache
from django.db.models import IntegerField, ForeignKey, CharField, TextField, ManyToManyField, CASCADE from django.db.models import IntegerField, ForeignKey, CharField, TextField, ManyToManyField, CASCADE
@ -22,9 +23,9 @@ class UserProfile(AbstractUser, CoreModel):
gender = CharField(max_length=8, verbose_name="性别", null=True, blank=True) gender = CharField(max_length=8, verbose_name="性别", null=True, blank=True)
remark = TextField(verbose_name="备注", null=True) remark = TextField(verbose_name="备注", null=True)
user_type = IntegerField(default=0, verbose_name="用户类型") user_type = IntegerField(default=0, verbose_name="用户类型")
post = ManyToManyField(to='Post', verbose_name='关联岗位', db_constraint=False) post = ManyToManyField(to='permission.Post', verbose_name='关联岗位', db_constraint=False)
role = ManyToManyField(to='Role', verbose_name='关联角色', db_constraint=False) role = ManyToManyField(to='permission.Role', verbose_name='关联角色', db_constraint=False)
dept = ForeignKey(to='Dept', verbose_name='归属部门', on_delete=CASCADE, db_constraint=False, null=True, blank=True) dept = ForeignKey(to='permission.Dept', verbose_name='归属部门', on_delete=CASCADE, db_constraint=False, null=True, blank=True)
@property @property
def get_user_interface_dict(self): def get_user_interface_dict(self):
@ -51,6 +52,7 @@ class UserProfile(AbstractUser, CoreModel):
return cache.delete(f'permission_interface_dict_{self.username}') return cache.delete(f'permission_interface_dict_{self.username}')
class Meta: class Meta:
abstract = settings.AUTH_USER_MODEL != 'permission.UserProfile'
verbose_name = '用户管理' verbose_name = '用户管理'
verbose_name_plural = verbose_name verbose_name_plural = verbose_name

View File

@ -1,10 +1,13 @@
from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from rest_framework.validators import UniqueValidator from rest_framework.validators import UniqueValidator
from ..op_drf.serializers import CustomModelSerializer from ..op_drf.serializers import CustomModelSerializer
from ..permission.models import Menu, Dept, Post, Role, UserProfile from ..permission.models import Menu, Dept, Post, Role
from ..system.models import MessagePush from ..system.models import MessagePush
UserProfile = get_user_model()
# ================================================= # # ================================================= #
# ************** 菜单管理 序列化器 ************** # # ************** 菜单管理 序列化器 ************** #

View File

@ -1,4 +1,4 @@
from django.contrib.auth import authenticate from django.contrib.auth import authenticate, get_user_model
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.views import APIView from rest_framework.views import APIView
@ -6,7 +6,7 @@ from .permissions import CommonPermission, DeptDestroyPermission
from ..op_drf.filters import DataLevelPermissionsFilter from ..op_drf.filters import DataLevelPermissionsFilter
from ..op_drf.viewsets import CustomModelViewSet from ..op_drf.viewsets import CustomModelViewSet
from ..permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter from ..permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter
from ..permission.models import Role, Menu, Dept, Post, UserProfile from ..permission.models import Role, Menu, Dept, Post
from ..permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \ from ..permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \
MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \ MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \
RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \ RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \
@ -15,6 +15,8 @@ from ..permission.serializers import UserProfileSerializer, MenuSerializer, Role
from ..system.models import DictDetails from ..system.models import DictDetails
from ..utils.response import SuccessResponse, ErrorResponse from ..utils.response import SuccessResponse, ErrorResponse
UserProfile = get_user_model()
class GetUserProfileView(APIView): class GetUserProfileView(APIView):
""" """

View File

@ -1,5 +1,7 @@
import os import os
from django.conf import settings
def getSql(filename): def getSql(filename):
""" """
@ -9,6 +11,10 @@ def getSql(filename):
""" """
abspath = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")) abspath = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))
pwd = os.path.join(abspath, 'scripts', filename) pwd = os.path.join(abspath, 'scripts', filename)
with open(pwd,'rb') as fp: with open(pwd, 'rb') as fp:
content = fp.read().decode('utf8') content = fp.read().decode('utf8')
if filename == "permission/permission_userprofile.sql":
user_name = "_".join(settings.AUTH_USER_MODEL.lower().split("."))
content = content.replace("permission_userprofile", user_name). \
replace("userprofile", settings.AUTH_USER_MODEL.lower().split(".")[-1])
return [ele for ele in content.split('\n') if not ele.startswith('--') and ele.strip(' ')] return [ele for ele in content.split('\n') if not ele.startswith('--') and ele.strip(' ')]

View File

@ -9,7 +9,7 @@ class DictDetails(CoreModel):
is_default = BooleanField(verbose_name="是否默认", default=False) is_default = BooleanField(verbose_name="是否默认", default=False)
status = CharField(max_length=2, verbose_name="字典状态") status = CharField(max_length=2, verbose_name="字典状态")
sort = CharField(max_length=256, verbose_name="字典排序") sort = CharField(max_length=256, verbose_name="字典排序")
dict_data = ForeignKey(to='DictData', on_delete=CASCADE, verbose_name="关联字典", db_constraint=False) dict_data = ForeignKey(to='system.DictData', on_delete=CASCADE, verbose_name="关联字典", db_constraint=False)
remark = CharField(max_length=256, verbose_name="备注", null=True, blank=True) remark = CharField(max_length=256, verbose_name="备注", null=True, blank=True)
@classmethod @classmethod

View File

@ -1,9 +1,9 @@
from django.conf import settings
from django.db import models from django.db import models
from django.db.models import * from django.db.models import *
from ...op_drf.fields import UpdateDateTimeField, CreateDateTimeField from ...op_drf.fields import UpdateDateTimeField, CreateDateTimeField
from ...op_drf.models import CoreModel from ...op_drf.models import CoreModel
from ...permission.models import UserProfile
""" """
消息通知模型 消息通知模型
@ -17,7 +17,7 @@ class MessagePush(CoreModel):
is_reviewed = BooleanField(default=True, verbose_name="是否审核") is_reviewed = BooleanField(default=True, verbose_name="是否审核")
status = CharField(max_length=8, verbose_name="通知状态") status = CharField(max_length=8, verbose_name="通知状态")
to_path = CharField(max_length=256, verbose_name="跳转路径", null=True, blank=True, ) to_path = CharField(max_length=256, verbose_name="跳转路径", null=True, blank=True, )
user = ManyToManyField(to="permission.UserProfile", user = ManyToManyField(to=settings.AUTH_USER_MODEL,
related_name="user", related_query_name="user_query", through='MessagePushUser', related_name="user", related_query_name="user_query", through='MessagePushUser',
through_fields=('message_push', 'user')) through_fields=('message_push', 'user'))
@ -34,7 +34,7 @@ class MessagePushUser(models.Model):
related_name="messagepushuser_message_push", related_name="messagepushuser_message_push",
verbose_name='消息通知', help_text='消息通知') verbose_name='消息通知', help_text='消息通知')
user = ForeignKey(UserProfile, on_delete=CASCADE, db_constraint=False, user = ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=CASCADE, db_constraint=False,
related_name="messagepushuser_user", related_name="messagepushuser_user",
verbose_name='用户', help_text='用户') verbose_name='用户', help_text='用户')
is_read = BooleanField(default=False, verbose_name="是否已读") is_read = BooleanField(default=False, verbose_name="是否已读")