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

# Conflicts:
#	dvadmin-ui/src/store/modules/permission.js
pull/26/MERGE
李强 2021-05-02 19:28:25 +08:00
commit dc57574e55
12 changed files with 90 additions and 31 deletions

View File

@ -50,9 +50,9 @@ github地址[https://github.com/liqianglog/django-vue-admin](https://github.c
## 在线体验
演示地址:[https://demo.django-vue-admin.com/](https://demo.django-vue-admin.com/) 账号admin 密码123456
演示地址:[http://demo.django-vue-admin.com/](http://demo.django-vue-admin.com/) 账号admin 密码123456
文档地址:[https://django-vue-admin.com/](https://django-vue-admin.com/)
文档地址:[http://django-vue-admin.com/](http://django-vue-admin.com/)
## 前端

View File

@ -48,19 +48,22 @@ class MonitorModelViewSet(CustomModelViewSet):
"""
pk = kwargs.get("pk")
queryset = self.filter_queryset(self.get_queryset())
queryset = queryset.filter(server__id=pk).order_by("-create_datetime")
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]
queryset = queryset.values('cpu_sys', 'mem_num', 'mem_sys', 'create_datetime')[::Interval_num][:100]
data = {
"cpu": [],
"memory": [],
"datetime": [],
}
for ele in queryset:
data["cpu"].append(float(ele.get('cpu_sys', 0)) / 100)
data["memory"].append(float(ele.get('mem_num', 0)) and round(float(ele.get('mem_sys', 0)) /
float(ele.get('mem_num', 0)), 4))
data["cpu"].append(round(float(ele.get('cpu_sys', 0)), 2))
data["datetime"].append(ele.get('create_datetime').strftime('%Y-%m-%d %H:%M:%S'))
data["memory"].append(round(float(ele.get('mem_num', 0)), 4) and round(float(ele.get('mem_sys', 0)) /
float(ele.get('mem_num', 0)) * 100,
2))
return SuccessResponse(data=data)
def get_monitor_info(self, request: Request, *args, **kwargs):

View File

@ -315,8 +315,9 @@ class ImportSerializerMixin:
# 导出模板
if request.method == 'GET':
# 示例数据
queryset = self.filter_queryset(self.get_queryset())
return SuccessResponse(
export_excel_save_model(request, self.import_field_data.values(), [], '导入用户数据模板.xls'))
export_excel_save_model(request, self.import_field_data.values(), [], f'导入{get_verbose_name(queryset)}模板.xls'))
updateSupport = request.data.get('updateSupport')
# 从excel中组织对应的数据结构然后使用序列化器保存
data = excel_to_data(request.data.get('file_url'), self.import_field_data)

View File

@ -33,6 +33,8 @@ class CustomModelSerializer(ModelSerializer):
return super().save(**kwargs)
def create(self, validated_data):
if self.context.get('request'):
self.request = self.context.get('request')
if self.request:
username = self.get_request_username()
if self.modifier_field_name in self.fields.fields:

View File

@ -0,0 +1,28 @@
"""
重写校验器返回字段
"""
from rest_framework.validators import UniqueValidator, qs_exists
from vadmin.utils.exceptions import APIException
class CustomUniqueValidator(UniqueValidator):
"""
继承,重写必填字段的验证器结果,防止字段暴露
"""
def __call__(self, value, serializer_field):
# Determine the underlying model field name. This may not be the
# same as the serializer field name if `source=<>` is set.
field_name = serializer_field.source_attrs[-1]
# Determine the existing instance, if this is an update operation.
instance = getattr(serializer_field.parent, 'instance', None)
queryset = self.queryset
queryset = self.filter_queryset(value, queryset, field_name)
queryset = self.exclude_current_instance(queryset, instance)
if qs_exists(queryset):
raise APIException(message=self.message)
def __repr__(self):
return super().__repr__()

View File

@ -1,8 +1,8 @@
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 ..op_drf.validator import CustomUniqueValidator
from ..permission.models import Menu, Dept, Post, Role
from ..system.models import MessagePush
@ -260,7 +260,8 @@ class UserProfileCreateUpdateSerializer(CustomModelSerializer):
post = PostSerializer(many=True, read_only=True)
role = RoleSerializer(many=True, read_only=True)
username = serializers.CharField(required=True, max_length=150,
validators=[UniqueValidator(queryset=UserProfile.objects.all(), message="用戶已存在")],
validators=[
CustomUniqueValidator(queryset=UserProfile.objects.all(), message="用戶已存在")],
error_messages={
"blank": "请输入用户名称",
"required": "用户名称不能为空",

View File

@ -121,3 +121,10 @@ INSERT INTO `permission_menu` (id, description, modifier, update_datetime, creat
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (88, '', 'admin', '2021-03-21 23:33:30.888568', '2021-03-21 23:33:30.888593', '2', NULL, '登录日志清空', 4, '1', NULL, NULL, '/admin/system/logininfor/clean/', 'DELETE', 'admin:system:logininfor:clean:delete', '1', '1', '1', 1, 62, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (90, '', 'admin', '2021-03-26 00:44:00.756139', '2021-03-26 00:43:14.390228', '2', NULL, '定时日志批量删除', 3, '1', NULL, NULL, '/admin/system/celery_log/{id}/', 'DELETE', 'admin:system:celery_log:{id}:delete', '1', '1', '1', 1, 79, '8');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (91, '', 'admin', '2021-03-26 00:44:36.135658', '2021-03-26 00:44:36.135679', '2', NULL, '定时日志清空', 4, '1', NULL, NULL, '/admin/system/celery_log/clean/', 'DELETE', 'admin:system:celery_log:clean:delete', '1', '1', '1', 1, 79, '8');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (92, '', 'admin', '2021-04-27 23:49:59.036636', '2021-04-27 23:44:54.512207', '1', 'server', '服务监控', 3, '1', '/monitor/server', 'vadmin/monitor/server/index', NULL, 'GET', NULL, '1', '1', '1', 1, 66, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (93, '', 'admin', '2021-04-27 23:57:46.633022', '2021-04-27 23:49:28.569029', '2', NULL, '服务监控查询', 1, '1', NULL, NULL, '/admin/monitor/server/', 'GET', 'admin:monitor:server:get', '1', '1', '1', 1, 92, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (94, '', 'admin', '2021-04-27 23:58:44.705142', '2021-04-27 23:58:13.384483', '2', NULL, '修改服务器信息', 2, '1', NULL, NULL, '/admin/monitor/server/{id}/', 'PUT', 'admin:monitor:server:{id}:put', '1', '1', '1', 1, 92, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (95, '', 'admin', '2021-04-27 23:59:29.530633', '2021-04-27 23:59:07.744938', '2', NULL, '修改监控信息', 3, '1', NULL, NULL, '/admin/monitor/monitor/enabled/', 'GET', 'admin:monitor:monitor:enabled:get', '1', '1', '1', 1, 92, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (96, '', 'admin', '2021-04-28 00:01:15.071889', '2021-04-27 23:59:48.612905', '2', NULL, '清空监控记录', 4, '1', NULL, NULL, '/admin/monitor/monitor/clean/', 'GET', 'admin:monitor:monitor:clean:get', '1', '1', '1', 1, 92, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (97, '', 'admin', '2021-05-02 19:12:06.813143', '2021-05-02 18:58:06.260280', '0', 'dashboard', '首页', 0, '1', '/home', NULL, NULL, 'GET', NULL, '1', '1', '1', 1, NULL, '1');
INSERT INTO `permission_menu` (id, description, modifier, update_datetime, create_datetime, menuType, icon, name, orderNum, isFrame, web_path, component_path, interface_path, interface_method, perms, status, visible, isCache, creator_id, parentId_id, dept_belong_id) VALUES (98, '', 'admin', '2021-05-02 19:10:34.233070', '2021-05-02 19:10:34.233125', '0', 'dashboard', '首页', 1, '1', 'index', 'index', NULL, 'GET', NULL, '1', '1', '1', 1, 97, '1');

View File

@ -56,14 +56,14 @@ export const constantRoutes = [
{
path: '',
component: Layout,
redirect: 'index',
redirect: '/home/index',
children: [
{
path: 'index',
component: (resolve) => require(['@/views/index'], resolve),
name: '首页',
meta: { title: '首页', icon: 'dashboard', noCache: true, affix: true }
}
// {
// path: 'index',
// component: (resolve) => require(['@/views/index'], resolve),
// name: '首页',
// meta: { title: '首页', icon: 'dashboard', noCache: true, affix: true }
// }
]
},
{

View File

@ -58,7 +58,11 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
if (route.children.length === 1 && route.children[0].path === 'index') {
route.alwaysShow = false
} else {
route.alwaysShow = true
}
} else {
delete route['children']
delete route['redirect']

View File

@ -74,14 +74,15 @@ export default {
serverInfo: VueTypes.object.isRequired,
lineChartKey: VueTypes.string.isRequired,
chartTitle: VueTypes.string.isRequired,
chartData: VueTypes.array.isRequired
chartData: VueTypes.array.isRequired,
},
data() {
return {
TIME_LIMIT_SETTING,
timeLimit: DEFAULT_TIME,
lineChartId: this.lineChartKey + 'Chart',
lineChartData: this.chartData
lineChartData: this.chartData,
lineChartTime: this.chartData
}
},
@ -107,9 +108,14 @@ export default {
let barGraph = echarts.init(document.getElementById(this.lineChartId))
//
barGraph.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}'
tooltip : {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985',
}
}
},
legend: {
left: 'center',
@ -120,7 +126,8 @@ export default {
type: 'category',
name: 'x',
splitLine: { show: false },
data: []
data:this.lineChartTime,
offset:20
},
grid: {
left: '1%',
@ -131,14 +138,19 @@ export default {
yAxis: {
type: 'value',
name: '使用率',
axisLabel: {
show: true,
interval: 'auto',
formatter: '{value}%'
},
},
series: [
{
name: '使用率',
type: 'line',
data: this.lineChartData
data: this.lineChartData,
}
]
],
})
},
changeTimeLimit(value) {
@ -146,8 +158,9 @@ export default {
this.getCurrentServerMonitorLogs()
},
getCurrentServerMonitorLogs() {
getMonitorLogs(this.serverInfo.id,{ as: { 'create_datetime__range': this.currentTimeLimitSetting.timeRange } }).then(results => {
getMonitorLogs(this.serverInfo.id, {as: JSON.stringify({create_datetime__range: this.currentTimeLimitSetting.timeRange})}).then(results => {
this.lineChartData = results.data[this.lineChartKey]
this.lineChartTime = results.data["datetime"]
this.drawBar()
}).catch(error => {
this.$message.warning(error.msg || `获取${this.chartTitle}数据失败!`)

View File

@ -115,7 +115,7 @@
<!-- 下方折线图 -->
<div class="server-monitor-bottom">
<!-- 折线图 -->
<el-card class="box-card server-monitor-line-chart" v-for="(key, index) in Object.keys(lineChartData)"
<el-card class="box-card server-monitor-line-chart" v-for="(key, index) in Object.keys(lineChartData).slice(0,2)"
:key="`${index}-${key}`">
<line-chart :line-chart-key="key"
:server-info="currentServer"
@ -313,7 +313,7 @@ export default {
},
/** 获取监控日志信息 */
getCurrentServerMonitorLogs() {
getMonitorLogs(this.currentServer.id, { as: { 'create_datetime__range': this.timeRange } }).then(results => {
getMonitorLogs(this.currentServer.id, { as: JSON.stringify( { 'create_datetime__range': this.timeRange })}).then(results => {
this.lineChartData = results.data
}).catch(error => {
this.msgError(error.msg || '获取监控日志信息出错误!')

View File

@ -117,7 +117,7 @@
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<router-link :to="'/dict/type/data/' + scope.row.id" class="link-type">
<router-link :to="hasPermi(['system:dict:type:get']) ?'/dict/type/data/' + scope.row.id :'#'" class="link-type">
<span>{{ scope.row.dictType }}</span>
</router-link>
</template>