操作日志前端完成
parent
38e09f556b
commit
f2f8fa241e
|
@ -118,7 +118,7 @@ USE_I18N = True
|
|||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
USE_TZ = False
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.11/howto/static-files/
|
||||
|
@ -316,4 +316,4 @@ CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
|
|||
|
||||
API_LOG_ENABLE = True
|
||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||
API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']
|
||||
# API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']
|
||||
|
|
|
@ -201,3 +201,12 @@ class CustomerModelViewLogger(ModelViewLogger):
|
|||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]删除{model_name}:[{instance}]')
|
||||
|
||||
def handle_other(self, request: Request, instance: Model = None, *args, **kwargs):
|
||||
"""
|
||||
仅 其他 请求才会触发此方法
|
||||
"""
|
||||
pass
|
||||
operator = self.user.username
|
||||
model_name = getattr(self.model, '_meta').verbose_name
|
||||
self.logger(f'{self.log_prefix}用户[username={operator}]其他请求{model_name}:[{instance}]')
|
||||
|
|
|
@ -5,7 +5,7 @@ django中间件
|
|||
from django.conf import settings
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
||||
from apps.vadmin.system.models import RequestLog
|
||||
from apps.vadmin.system.models import OperationLog
|
||||
from ..utils.request_util import get_request_ip, get_request_data, get_request_path, get_browser, get_os, \
|
||||
get_login_location
|
||||
|
||||
|
@ -39,7 +39,7 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
|||
'request_method': request.method,
|
||||
'request_path': request.request_path,
|
||||
'request_body': body,
|
||||
'response_code': response.status_code,
|
||||
'response_code': response.data.get('code'),
|
||||
'request_location': get_login_location(request),
|
||||
'request_os': get_os(request),
|
||||
'request_browser': get_browser(request),
|
||||
|
@ -48,7 +48,7 @@ class ApiLoggingMiddleware(MiddlewareMixin):
|
|||
'json_result': {"code": response.data.get('code'), "msg": response.data.get('msg')},
|
||||
'request_modular': request.session.get('model_name'),
|
||||
}
|
||||
log = RequestLog(**info)
|
||||
log = OperationLog(**info)
|
||||
log.save()
|
||||
|
||||
def process_request(self, request):
|
||||
|
|
|
@ -7,6 +7,7 @@ from rest_framework.request import Request
|
|||
|
||||
from .response import SuccessResponse
|
||||
from ..utils.export_excel import excel_to_data, export_excel_save_model
|
||||
from ..utils.request_util import get_verbose_name
|
||||
|
||||
|
||||
class CreateModelMixin(mixins.CreateModelMixin):
|
||||
|
@ -35,10 +36,10 @@ class ListModelMixin(mixins.ListModelMixin):
|
|||
list_serializer_class = None
|
||||
|
||||
def list(self, request: Request, *args, **kwargs):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
page = self.paginate_queryset(queryset)
|
||||
if hasattr(self, 'handle_logging'):
|
||||
self.handle_logging(request, *args, **kwargs)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
if getattr(self, 'values_queryset', None):
|
||||
return self.get_paginated_response(page)
|
||||
|
@ -298,8 +299,7 @@ class ImportSerializerMixin:
|
|||
# 导入序列化器
|
||||
import_serializer_class = None
|
||||
|
||||
|
||||
@transaction.atomic # Django 事物
|
||||
@transaction.atomic # Django 事物
|
||||
def importTemplate(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
用户导人模板
|
||||
|
@ -358,4 +358,5 @@ class ExportSerializerMixin:
|
|||
% self.__class__.__name__
|
||||
)
|
||||
data = self.export_serializer_class(self.get_queryset(), many=True).data
|
||||
return SuccessResponse(export_excel_save_model(request, self.export_field_data, data, '导出用户数据.xls'))
|
||||
return SuccessResponse(export_excel_save_model(request, self.export_field_data, data,
|
||||
f'导出{get_verbose_name(self.get_queryset())}.xls'))
|
||||
|
|
|
@ -72,7 +72,7 @@ class CustomAPIView(APIView):
|
|||
method = request.method.lower()
|
||||
for view_logger in view_loggers:
|
||||
view_logger.handle(request, *args, **kwargs)
|
||||
logger_fun = getattr(view_logger, f'handle_{method}', None)
|
||||
logger_fun = getattr(view_logger, f'handle_{method}', f'handle_other')
|
||||
if logger_fun and isinstance(logger_fun, (FunctionType, MethodType)):
|
||||
logger_fun(request, *args, **kwargs)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import django_filters
|
||||
|
||||
from .models import LoginInfor
|
||||
from .models import LoginInfor, OperationLog
|
||||
from ..system.models import DictDetails, DictData, ConfigSettings, MessagePush, SaveFile
|
||||
|
||||
|
||||
|
@ -70,3 +70,15 @@ class LoginInforFilter(django_filters.rest_framework.FilterSet):
|
|||
class Meta:
|
||||
model = LoginInfor
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class OperationLogFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
操作日志 简单过滤器
|
||||
"""
|
||||
request_modular = django_filters.CharFilter(lookup_expr='icontains')
|
||||
creator_username = django_filters.CharFilter(field_name='creator__username', lookup_expr='icontains')
|
||||
|
||||
class Meta:
|
||||
model = OperationLog
|
||||
fields = '__all__'
|
||||
|
|
|
@ -6,5 +6,5 @@ from ..models.save_file import SaveFile
|
|||
from ..models.message_push import MessagePush
|
||||
from ..models.message_push import MessagePushUser
|
||||
from ..models.logininfor import LoginInfor
|
||||
from ..models.request_log import RequestLog
|
||||
from ..models.operation_log import OperationLog
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ from django.db.models import TextField, CharField, BooleanField
|
|||
from ...op_drf.models import CoreModel
|
||||
|
||||
|
||||
class RequestLog(CoreModel):
|
||||
class OperationLog(CoreModel):
|
||||
request_modular = CharField(max_length=64, verbose_name="请求模块", null=True, blank=True)
|
||||
request_path = CharField(max_length=400, verbose_name="请求地址", null=True, blank=True)
|
||||
request_body = TextField(verbose_name="请求参数", null=True, blank=True)
|
||||
request_method = CharField(max_length=64, verbose_name="请求方式", null=True, blank=True)
|
||||
request_msg = CharField(max_length=64, verbose_name="操作说明", null=True, blank=True)
|
||||
request_msg = TextField(verbose_name="操作说明", null=True, blank=True)
|
||||
request_ip = CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True)
|
||||
request_browser = CharField(max_length=32, verbose_name="请求浏览器", null=True, blank=True)
|
||||
response_code = CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True)
|
|
@ -1,6 +1,6 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from .models import LoginInfor
|
||||
from .models import LoginInfor, OperationLog
|
||||
from ..op_drf.serializers import CustomModelSerializer
|
||||
from ..system.models import DictData, DictDetails, ConfigSettings, SaveFile, MessagePush, MessagePushUser
|
||||
|
||||
|
@ -196,6 +196,7 @@ class ExportMessagePushSerializer(CustomModelSerializer):
|
|||
'id', 'title', 'content', 'message_type', 'is_reviewed', 'status', 'users', 'creator', 'modifier',
|
||||
'update_datetime', 'create_datetime')
|
||||
|
||||
|
||||
class MessagePushUserSerializer(CustomModelSerializer):
|
||||
"""
|
||||
消息通知 用户查询简单序列化器
|
||||
|
@ -208,7 +209,7 @@ class MessagePushUserSerializer(CustomModelSerializer):
|
|||
# return UserProfileSerializer(obj.user.all(), many=True).data
|
||||
# 返回这个消息是否已读
|
||||
def get_is_read(self, obj):
|
||||
object = MessagePushUser.objects.filter(message_push=obj,user=self.context.get('request').user).first()
|
||||
object = MessagePushUser.objects.filter(message_push=obj, user=self.context.get('request').user).first()
|
||||
return object.is_read if object else False
|
||||
|
||||
class Meta:
|
||||
|
@ -218,6 +219,7 @@ class MessagePushUserSerializer(CustomModelSerializer):
|
|||
def save(self, **kwargs):
|
||||
return super().save(**kwargs)
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 登录日志 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
@ -230,3 +232,30 @@ class LoginInforSerializer(CustomModelSerializer):
|
|||
class Meta:
|
||||
model = LoginInfor
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
# ================================================= #
|
||||
# ************** 操作日志 序列化器 ************** #
|
||||
# ================================================= #
|
||||
|
||||
class OperationLogSerializer(CustomModelSerializer):
|
||||
"""
|
||||
操作日志 简单序列化器
|
||||
"""
|
||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = OperationLog
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class ExportOperationLogSerializer(CustomModelSerializer):
|
||||
"""
|
||||
导出 操作日志 简单序列化器
|
||||
"""
|
||||
creator_name = serializers.SlugRelatedField(slug_field="username", source="creator", read_only=True)
|
||||
class Meta:
|
||||
model = OperationLog
|
||||
fields = ('request_modular', 'request_path', 'request_body', 'request_method', 'request_msg', 'request_ip',
|
||||
'request_browser', 'response_code', 'request_location', 'request_os', 'json_result', 'status',
|
||||
'creator_name')
|
||||
|
|
|
@ -2,7 +2,8 @@ from django.urls import re_path
|
|||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from ..system.views import DictDataModelViewSet, DictDetailsModelViewSet, \
|
||||
ConfigSettingsModelViewSet, SaveFileModelViewSet, MessagePushModelViewSet, LoginInforModelViewSet
|
||||
ConfigSettingsModelViewSet, SaveFileModelViewSet, MessagePushModelViewSet, LoginInforModelViewSet, \
|
||||
OperationLogModelViewSet
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register(r'dict/type', DictDataModelViewSet)
|
||||
|
@ -11,6 +12,8 @@ router.register(r'config', ConfigSettingsModelViewSet)
|
|||
router.register(r'savefile', SaveFileModelViewSet)
|
||||
router.register(r'message', MessagePushModelViewSet)
|
||||
router.register(r'logininfor', LoginInforModelViewSet)
|
||||
router.register(r'operation_log', OperationLogModelViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
re_path('dict/get/type/(?P<pk>.*)/', DictDetailsModelViewSet.as_view({'get': 'dict_details_list'})),
|
||||
re_path('config/configKey/(?P<pk>.*)/', ConfigSettingsModelViewSet.as_view({'get': 'get_config_key'})),
|
||||
|
@ -30,5 +33,9 @@ urlpatterns = [
|
|||
re_path('message/user_messages/', MessagePushModelViewSet.as_view({'get': 'get_user_messages', })),
|
||||
# 改为已读
|
||||
re_path('message/is_read/(?P<pk>.*)/', MessagePushModelViewSet.as_view({'put': 'update_is_read', })),
|
||||
# 清空操作日志
|
||||
re_path('operation_log/clean/', OperationLogModelViewSet.as_view({'delete': 'clean_all', })),
|
||||
# 导出操作日志
|
||||
re_path('operation_log/export/', OperationLogModelViewSet.as_view({'get': 'export', })),
|
||||
]
|
||||
urlpatterns += router.urls
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
from django.db.models import Q
|
||||
from rest_framework.request import Request
|
||||
|
||||
from .models import LoginInfor
|
||||
from .models import LoginInfor, OperationLog
|
||||
from ..op_drf.filters import DataLevelPermissionsFilter
|
||||
from ..op_drf.viewsets import CustomModelViewSet
|
||||
from ..system.filters import DictDetailsFilter, DictDataFilter, ConfigSettingsFilter, MessagePushFilter, \
|
||||
SaveFileFilter, LoginInforFilter
|
||||
SaveFileFilter, LoginInforFilter, OperationLogFilter
|
||||
from ..system.models import DictData, DictDetails, ConfigSettings, SaveFile, MessagePush
|
||||
from ..system.models import MessagePushUser
|
||||
from ..system.serializers import DictDataSerializer, DictDataCreateUpdateSerializer, DictDetailsSerializer, \
|
||||
DictDetailsCreateUpdateSerializer, DictDetailsListSerializer, ConfigSettingsSerializer, \
|
||||
ConfigSettingsCreateUpdateSerializer, SaveFileSerializer, SaveFileCreateUpdateSerializer, \
|
||||
ExportConfigSettingsSerializer, ExportDictDataSerializer, ExportDictDetailsSerializer, \
|
||||
MessagePushSerializer, MessagePushCreateUpdateSerializer, ExportMessagePushSerializer, LoginInforSerializer
|
||||
MessagePushSerializer, MessagePushCreateUpdateSerializer, ExportMessagePushSerializer, LoginInforSerializer, \
|
||||
OperationLogSerializer, ExportOperationLogSerializer
|
||||
from ..utils.export_excel import export_excel_save_model
|
||||
from ..utils.response import SuccessResponse
|
||||
|
||||
|
@ -224,3 +225,28 @@ class LoginInforModelViewSet(CustomModelViewSet):
|
|||
filter_class = LoginInforFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
ordering = 'create_datetime' # 默认排序
|
||||
|
||||
|
||||
class OperationLogModelViewSet(CustomModelViewSet):
|
||||
"""
|
||||
操作日志 模型的CRUD视图
|
||||
"""
|
||||
queryset = OperationLog.objects.all()
|
||||
serializer_class = OperationLogSerializer
|
||||
filter_class = OperationLogFilter
|
||||
extra_filter_backends = [DataLevelPermissionsFilter]
|
||||
ordering = '-create_datetime' # 默认排序
|
||||
export_field_data = ['请求模块', '请求地址', '请求参数', '请求方式', '操作说明', '请求ip地址',
|
||||
'请求浏览器', '响应状态码', '操作地点', '操作系统', '返回信息', '响应状态', '操作用户名']
|
||||
export_serializer_class = ExportOperationLogSerializer
|
||||
|
||||
def clean_all(self, request: Request, *args, **kwargs):
|
||||
"""
|
||||
清空操作日志
|
||||
:param request:
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
self.get_queryset().delete()
|
||||
return SuccessResponse(msg="清空成功")
|
||||
|
|
|
@ -4,6 +4,7 @@ import traceback
|
|||
from rest_framework import serializers, exceptions
|
||||
from rest_framework.views import set_rollback
|
||||
|
||||
from .request_util import get_verbose_name
|
||||
from .response import ErrorResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -17,9 +18,9 @@ class APIException(Exception):
|
|||
"""
|
||||
|
||||
def __init__(self, code=201, message='API异常', args=('API异常',)):
|
||||
self.args = args
|
||||
self.code = code
|
||||
self.message = message
|
||||
args = args
|
||||
code = code
|
||||
message = message
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
@ -36,7 +37,7 @@ class FrameworkException(Exception):
|
|||
|
||||
def __init__(self, message='框架异常', *args: object, **kwargs: object) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.message = message
|
||||
message = message
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.message}"
|
||||
|
@ -64,6 +65,9 @@ def op_exception_handler(ex, context):
|
|||
"""
|
||||
msg = ''
|
||||
code = '201'
|
||||
request = context.get('request')
|
||||
request.session['model_name'] = get_verbose_name(view=context.get('view'))
|
||||
|
||||
if isinstance(ex, AuthenticationFailed):
|
||||
code = 401
|
||||
msg = ex.detail
|
||||
|
|
|
@ -172,3 +172,21 @@ def get_login_location(request, *args, **kwargs):
|
|||
content = r.content.decode('GBK')
|
||||
return content.replace('\r', '').replace('\n', '')
|
||||
return ""
|
||||
|
||||
|
||||
def get_verbose_name(queryset=None, view=None, model=None):
|
||||
"""
|
||||
获取 verbose_name
|
||||
:param request:
|
||||
:param view:
|
||||
:return:
|
||||
"""
|
||||
if queryset and hasattr(queryset, 'model'):
|
||||
model = queryset.model
|
||||
elif view and hasattr(view.get_queryset(), 'model'):
|
||||
model = view.get_queryset().model
|
||||
elif view and hasattr(view.get_serializer(), 'Meta') and hasattr(view.get_serializer().Meta, 'model'):
|
||||
model = view.get_serializer().Meta.model
|
||||
if model:
|
||||
return getattr(model, '_meta').verbose_name
|
||||
return ""
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 查询操作日志列表
|
||||
export function list(query) {
|
||||
return request({
|
||||
url: '/admin/system/operation_log/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 删除操作日志
|
||||
export function delOperationLog(operId) {
|
||||
return request({
|
||||
url: '/admin/system/operation_log/' + operId + '/',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 清空操作日志
|
||||
export function cleanOperationLog() {
|
||||
return request({
|
||||
url: '/admin/system/operation_log/clean/',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 导出操作日志
|
||||
export function exportOperationLog(query) {
|
||||
return request({
|
||||
url: '/admin/system/operation_log/export/',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
|
@ -98,6 +98,18 @@ export const constantRoutes = [
|
|||
meta: { title: '字典数据', icon: '' }
|
||||
}
|
||||
]
|
||||
},{
|
||||
path: '/operlog',
|
||||
component: Layout,
|
||||
hidden: false,
|
||||
children: [
|
||||
{
|
||||
path: 'log',
|
||||
component: (resolve) => require(['@/views/vadmin/system/operlog'], resolve),
|
||||
name: 'Data',
|
||||
meta: { title: '操作日志', icon: '' }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -56,16 +56,13 @@ export function resetForm(refName) {
|
|||
// 添加日期范围
|
||||
export function addDateRange(params, dateRange, propName) {
|
||||
var search = params;
|
||||
search.params = {};
|
||||
if (null != dateRange && '' != dateRange) {
|
||||
if (typeof(propName) === "undefined") {
|
||||
search.params["beginTime"] = dateRange[0];
|
||||
search.params["endTime"] = dateRange[1];
|
||||
} else {
|
||||
search.params["begin" + propName] = dateRange[0];
|
||||
search.params["end" + propName] = dateRange[1];
|
||||
}
|
||||
// create_datetime__range = this.dateRange
|
||||
var dateTime=new Date();
|
||||
|
||||
search.as = JSON.stringify({create_datetime__range : dateRange});
|
||||
}
|
||||
console.log(11,search)
|
||||
return search;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="系统模块" prop="request_modular">
|
||||
<el-input
|
||||
v-model="queryParams.request_modular"
|
||||
placeholder="请输入系统模块"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人员" prop="creator_name">
|
||||
<el-input
|
||||
v-model="queryParams.creator_name"
|
||||
placeholder="请输入操作人员"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="操作状态"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="['00:00:00', '23:59:59']"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
@click="handleClean"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['system:config:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="日志编号" align="center" prop="id" />
|
||||
<el-table-column label="系统模块" align="center" prop="request_modular" />
|
||||
<el-table-column label="请求方式" align="center" prop="request_method" />
|
||||
<el-table-column label="操作人员" align="center" prop="creator_name" />
|
||||
<el-table-column label="主机" align="center" prop="request_ip" width="130" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作地点" align="center" prop="request_location" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作状态" align="center" prop="status" :formatter="statusFormat" />
|
||||
<el-table-column label="操作日期" align="center" prop="create_datetime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.create_datetime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row,scope.index)"
|
||||
v-hasPermi="['monitor:operlog:query']"
|
||||
>详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 操作日志详细 -->
|
||||
<el-dialog title="操作日志详细" :visible.sync="open" width="700px" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="100px" size="mini">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作模块:">{{ form.request_modular }} / {{ form.request_msg }}</el-form-item>
|
||||
<el-form-item
|
||||
label="登录信息:"
|
||||
>{{ form.creator_name }} / {{ form.request_ip }} / {{ form.request_location }} / {{ form.request_browser }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="请求地址:">{{ form.request_path }}</el-form-item>
|
||||
<el-form-item label="请求方式:">{{ form.request_method }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="请求参数:">{{ form.request_body }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="返回参数:">{{ form.json_result }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="返回状态码:">{{ form.response_code }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作状态:">
|
||||
<div v-if="form.status === true">正常</div>
|
||||
<div v-else-if="form.status === false">失败</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作时间:">{{ parseTime(form.create_datetime) }}</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="24">-->
|
||||
<!-- <el-form-item label="异常信息:" v-if="form.status === false">{{ form.json_result }}</el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {cleanOperationLog, delOperationLog, exportOperationLog, list} from "@/api/vadmin/system/operationlog";
|
||||
|
||||
export default {
|
||||
name: "Operlog",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 类型数据字典
|
||||
statusOptions: [{dictLabel: '成功', dictValue: true}, {dictLabel: '失败', dictValue: false}],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
request_modular: undefined,
|
||||
creator_name: undefined,
|
||||
status: undefined
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询登录日志 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
list(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
|
||||
this.list = response.data.results;
|
||||
this.total = response.data.count;
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
// 操作日志状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status);
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 详细按钮操作 */
|
||||
handleView(row) {
|
||||
this.open = true;
|
||||
this.form = row;
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ids = row.id || this.ids;
|
||||
this.$confirm('是否确认删除日志编号为"' + ids + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return delOperationLog(ids);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 清空按钮操作 */
|
||||
handleClean() {
|
||||
this.$confirm('是否确认清空所有操作日志数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return cleanOperationLog();
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("清空成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$confirm('是否确认导出所有操作日志数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportOperationLog(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.data.file_url,response.data.name);
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue