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:
dvadmin-ui:
container_name: dvadmin-ui
ports:
- "8080:8080"
build:
context: ./
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_sys = CharField(max_length=32, verbose_name='内存已使用大小(KB)')
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:
verbose_name = '服务器监控信息'

View File

@ -9,7 +9,7 @@ class SysFiles(CoreModel):
type_name = CharField(max_length=32, verbose_name='盘符类型')
total = 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:
verbose_name = '系统磁盘'

View File

@ -13,7 +13,18 @@ class ServerSerializer(CustomModelSerializer):
class Meta:
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)
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/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 .filters import ServerFilter, MonitorFilter
from .models import Server, Monitor
from .serializers import ServerSerializer, MonitorSerializer
from ..op_drf.response import SuccessResponse
from .models import Server, Monitor, SysFiles
from .serializers import ServerSerializer, MonitorSerializer, UpdateServerSerializer
from ..op_drf.response import SuccessResponse, ErrorResponse
from ..op_drf.viewsets import CustomModelViewSet
from ..permission.permissions import CommonPermission
from ..system.models import ConfigSettings
@ -16,6 +16,7 @@ class ServerModelViewSet(CustomModelViewSet):
"""
queryset = Server.objects.all()
serializer_class = ServerSerializer
update_serializer_class = UpdateServerSerializer
# extra_filter_backends = [DataLevelPermissionsFilter]
filter_class = ServerFilter
update_extra_permission_classes = (CommonPermission,)
@ -37,7 +38,80 @@ class MonitorModelViewSet(CustomModelViewSet):
create_extra_permission_classes = (CommonPermission,)
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):
"""
最新的服务器状态信息
: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()
if not periodictask_obj:
@ -73,33 +147,15 @@ class MonitorModelViewSet(CustomModelViewSet):
config_obj.remark = "定时清理多余-系统监控信息默认30天"
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:
# 更新监控状态
periodictask_obj.enabled = True if enabled == "1" else False
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.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:
config_obj.configValue = save_days
config_obj.save()

View File

@ -1,3 +1,4 @@
from django.conf import settings
from django.db import models
from django.db.models import SET_NULL
@ -24,7 +25,7 @@ class CoreModel(models.Model):
增加审计字段, 覆盖字段时, 字段名称请勿修改, 必须统一审计字段名称
"""
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) # 创建者
modifier = ModifierCharField() # 修改者
dept_belong_id = models.CharField(max_length=64, verbose_name="数据归属部门", null=True, blank=True)

View File

@ -1,8 +1,11 @@
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
UserProfile = get_user_model()
class MenuFilter(django_filters.rest_framework.FilterSet):
"""

View File

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

View File

@ -11,7 +11,7 @@ class Dept(CoreModel):
phone = 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)
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)
class Meta:

View File

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

View File

@ -1,5 +1,6 @@
from uuid import uuid4
from django.conf import settings
from django.contrib.auth.models import UserManager, AbstractUser
from django.core.cache import cache
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)
remark = TextField(verbose_name="备注", null=True)
user_type = IntegerField(default=0, verbose_name="用户类型")
post = ManyToManyField(to='Post', verbose_name='关联岗位', db_constraint=False)
role = ManyToManyField(to='Role', verbose_name='关联角色', db_constraint=False)
dept = ForeignKey(to='Dept', verbose_name='归属部门', on_delete=CASCADE, db_constraint=False, null=True, blank=True)
post = ManyToManyField(to='permission.Post', verbose_name='关联岗位', db_constraint=False)
role = ManyToManyField(to='permission.Role', verbose_name='关联角色', db_constraint=False)
dept = ForeignKey(to='permission.Dept', verbose_name='归属部门', on_delete=CASCADE, db_constraint=False, null=True, blank=True)
@property
def get_user_interface_dict(self):
@ -51,6 +52,7 @@ class UserProfile(AbstractUser, CoreModel):
return cache.delete(f'permission_interface_dict_{self.username}')
class Meta:
abstract = settings.AUTH_USER_MODEL != 'permission.UserProfile'
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.validators import UniqueValidator
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
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.views import APIView
@ -6,7 +6,7 @@ from .permissions import CommonPermission, DeptDestroyPermission
from ..op_drf.filters import DataLevelPermissionsFilter
from ..op_drf.viewsets import CustomModelViewSet
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, \
MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \
RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \
@ -15,6 +15,8 @@ from ..permission.serializers import UserProfileSerializer, MenuSerializer, Role
from ..system.models import DictDetails
from ..utils.response import SuccessResponse, ErrorResponse
UserProfile = get_user_model()
class GetUserProfileView(APIView):
"""

View File

@ -1,5 +1,7 @@
import os
from django.conf import settings
def getSql(filename):
"""
@ -11,4 +13,8 @@ def getSql(filename):
pwd = os.path.join(abspath, 'scripts', filename)
with open(pwd, 'rb') as fp:
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(' ')]

View File

@ -9,7 +9,7 @@ class DictDetails(CoreModel):
is_default = BooleanField(verbose_name="是否默认", default=False)
status = CharField(max_length=2, 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)
@classmethod

View File

@ -1,9 +1,9 @@
from django.conf import settings
from django.db import models
from django.db.models import *
from ...op_drf.fields import UpdateDateTimeField, CreateDateTimeField
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="是否审核")
status = CharField(max_length=8, verbose_name="通知状态")
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',
through_fields=('message_push', 'user'))
@ -34,7 +34,7 @@ class MessagePushUser(models.Model):
related_name="messagepushuser_message_push",
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",
verbose_name='用户', help_text='用户')
is_read = BooleanField(default=False, verbose_name="是否已读")