操作日志前端完成

pull/2/head
李强 2021-03-21 11:24:50 +08:00
parent 38e09f556b
commit f2f8fa241e
17 changed files with 475 additions and 33 deletions

View File

@ -118,7 +118,7 @@ USE_I18N = True
USE_L10N = True USE_L10N = True
USE_TZ = True USE_TZ = False
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/ # 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_ENABLE = True
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE'] # API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE'] # API_LOG_METHODS = ['POST', 'DELETE'] # ['POST', 'DELETE']

View File

@ -201,3 +201,12 @@ class CustomerModelViewLogger(ModelViewLogger):
operator = self.user.username operator = self.user.username
model_name = getattr(self.model, '_meta').verbose_name model_name = getattr(self.model, '_meta').verbose_name
self.logger(f'{self.log_prefix}用户[username={operator}]删除{model_name}:[{instance}]') 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}]')

View File

@ -5,7 +5,7 @@ django中间件
from django.conf import settings from django.conf import settings
from django.utils.deprecation import MiddlewareMixin 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, \ from ..utils.request_util import get_request_ip, get_request_data, get_request_path, get_browser, get_os, \
get_login_location get_login_location
@ -39,7 +39,7 @@ class ApiLoggingMiddleware(MiddlewareMixin):
'request_method': request.method, 'request_method': request.method,
'request_path': request.request_path, 'request_path': request.request_path,
'request_body': body, 'request_body': body,
'response_code': response.status_code, 'response_code': response.data.get('code'),
'request_location': get_login_location(request), 'request_location': get_login_location(request),
'request_os': get_os(request), 'request_os': get_os(request),
'request_browser': get_browser(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')}, 'json_result': {"code": response.data.get('code'), "msg": response.data.get('msg')},
'request_modular': request.session.get('model_name'), 'request_modular': request.session.get('model_name'),
} }
log = RequestLog(**info) log = OperationLog(**info)
log.save() log.save()
def process_request(self, request): def process_request(self, request):

View File

@ -7,6 +7,7 @@ from rest_framework.request import Request
from .response import SuccessResponse from .response import SuccessResponse
from ..utils.export_excel import excel_to_data, export_excel_save_model from ..utils.export_excel import excel_to_data, export_excel_save_model
from ..utils.request_util import get_verbose_name
class CreateModelMixin(mixins.CreateModelMixin): class CreateModelMixin(mixins.CreateModelMixin):
@ -35,10 +36,10 @@ class ListModelMixin(mixins.ListModelMixin):
list_serializer_class = None list_serializer_class = None
def list(self, request: Request, *args, **kwargs): def list(self, request: Request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if hasattr(self, 'handle_logging'): if hasattr(self, 'handle_logging'):
self.handle_logging(request, *args, **kwargs) self.handle_logging(request, *args, **kwargs)
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None: if page is not None:
if getattr(self, 'values_queryset', None): if getattr(self, 'values_queryset', None):
return self.get_paginated_response(page) return self.get_paginated_response(page)
@ -298,7 +299,6 @@ class ImportSerializerMixin:
# 导入序列化器 # 导入序列化器
import_serializer_class = None import_serializer_class = None
@transaction.atomic # Django 事物 @transaction.atomic # Django 事物
def importTemplate(self, request: Request, *args, **kwargs): def importTemplate(self, request: Request, *args, **kwargs):
""" """
@ -358,4 +358,5 @@ class ExportSerializerMixin:
% self.__class__.__name__ % self.__class__.__name__
) )
data = self.export_serializer_class(self.get_queryset(), many=True).data 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'))

View File

@ -72,7 +72,7 @@ class CustomAPIView(APIView):
method = request.method.lower() method = request.method.lower()
for view_logger in view_loggers: for view_logger in view_loggers:
view_logger.handle(request, *args, **kwargs) 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)): if logger_fun and isinstance(logger_fun, (FunctionType, MethodType)):
logger_fun(request, *args, **kwargs) logger_fun(request, *args, **kwargs)

View File

@ -1,6 +1,6 @@
import django_filters import django_filters
from .models import LoginInfor from .models import LoginInfor, OperationLog
from ..system.models import DictDetails, DictData, ConfigSettings, MessagePush, SaveFile from ..system.models import DictDetails, DictData, ConfigSettings, MessagePush, SaveFile
@ -70,3 +70,15 @@ class LoginInforFilter(django_filters.rest_framework.FilterSet):
class Meta: class Meta:
model = LoginInfor model = LoginInfor
fields = '__all__' 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__'

View File

@ -6,5 +6,5 @@ from ..models.save_file import SaveFile
from ..models.message_push import MessagePush from ..models.message_push import MessagePush
from ..models.message_push import MessagePushUser from ..models.message_push import MessagePushUser
from ..models.logininfor import LoginInfor from ..models.logininfor import LoginInfor
from ..models.request_log import RequestLog from ..models.operation_log import OperationLog

View File

@ -3,12 +3,12 @@ from django.db.models import TextField, CharField, BooleanField
from ...op_drf.models import CoreModel 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_modular = CharField(max_length=64, verbose_name="请求模块", null=True, blank=True)
request_path = CharField(max_length=400, 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_body = TextField(verbose_name="请求参数", null=True, blank=True)
request_method = CharField(max_length=64, 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_ip = CharField(max_length=32, verbose_name="请求ip地址", null=True, blank=True)
request_browser = CharField(max_length=32, verbose_name="请求浏览器", 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) response_code = CharField(max_length=32, verbose_name="响应状态码", null=True, blank=True)

View File

@ -1,6 +1,6 @@
from rest_framework import serializers from rest_framework import serializers
from .models import LoginInfor from .models import LoginInfor, OperationLog
from ..op_drf.serializers import CustomModelSerializer from ..op_drf.serializers import CustomModelSerializer
from ..system.models import DictData, DictDetails, ConfigSettings, SaveFile, MessagePush, MessagePushUser 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', 'id', 'title', 'content', 'message_type', 'is_reviewed', 'status', 'users', 'creator', 'modifier',
'update_datetime', 'create_datetime') 'update_datetime', 'create_datetime')
class MessagePushUserSerializer(CustomModelSerializer): class MessagePushUserSerializer(CustomModelSerializer):
""" """
消息通知 用户查询简单序列化器 消息通知 用户查询简单序列化器
@ -218,6 +219,7 @@ class MessagePushUserSerializer(CustomModelSerializer):
def save(self, **kwargs): def save(self, **kwargs):
return super().save(**kwargs) return super().save(**kwargs)
# ================================================= # # ================================================= #
# ************** 登录日志 序列化器 ************** # # ************** 登录日志 序列化器 ************** #
# ================================================= # # ================================================= #
@ -230,3 +232,30 @@ class LoginInforSerializer(CustomModelSerializer):
class Meta: class Meta:
model = LoginInfor model = LoginInfor
fields = "__all__" 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')

View File

@ -2,7 +2,8 @@ from django.urls import re_path
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from ..system.views import DictDataModelViewSet, DictDetailsModelViewSet, \ from ..system.views import DictDataModelViewSet, DictDetailsModelViewSet, \
ConfigSettingsModelViewSet, SaveFileModelViewSet, MessagePushModelViewSet, LoginInforModelViewSet ConfigSettingsModelViewSet, SaveFileModelViewSet, MessagePushModelViewSet, LoginInforModelViewSet, \
OperationLogModelViewSet
router = DefaultRouter() router = DefaultRouter()
router.register(r'dict/type', DictDataModelViewSet) router.register(r'dict/type', DictDataModelViewSet)
@ -11,6 +12,8 @@ router.register(r'config', ConfigSettingsModelViewSet)
router.register(r'savefile', SaveFileModelViewSet) router.register(r'savefile', SaveFileModelViewSet)
router.register(r'message', MessagePushModelViewSet) router.register(r'message', MessagePushModelViewSet)
router.register(r'logininfor', LoginInforModelViewSet) router.register(r'logininfor', LoginInforModelViewSet)
router.register(r'operation_log', OperationLogModelViewSet)
urlpatterns = [ urlpatterns = [
re_path('dict/get/type/(?P<pk>.*)/', DictDetailsModelViewSet.as_view({'get': 'dict_details_list'})), 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'})), 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/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('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 urlpatterns += router.urls

View File

@ -1,18 +1,19 @@
from django.db.models import Q from django.db.models import Q
from rest_framework.request import Request from rest_framework.request import Request
from .models import LoginInfor from .models import LoginInfor, OperationLog
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 ..system.filters import DictDetailsFilter, DictDataFilter, ConfigSettingsFilter, MessagePushFilter, \ 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 DictData, DictDetails, ConfigSettings, SaveFile, MessagePush
from ..system.models import MessagePushUser from ..system.models import MessagePushUser
from ..system.serializers import DictDataSerializer, DictDataCreateUpdateSerializer, DictDetailsSerializer, \ from ..system.serializers import DictDataSerializer, DictDataCreateUpdateSerializer, DictDetailsSerializer, \
DictDetailsCreateUpdateSerializer, DictDetailsListSerializer, ConfigSettingsSerializer, \ DictDetailsCreateUpdateSerializer, DictDetailsListSerializer, ConfigSettingsSerializer, \
ConfigSettingsCreateUpdateSerializer, SaveFileSerializer, SaveFileCreateUpdateSerializer, \ ConfigSettingsCreateUpdateSerializer, SaveFileSerializer, SaveFileCreateUpdateSerializer, \
ExportConfigSettingsSerializer, ExportDictDataSerializer, ExportDictDetailsSerializer, \ ExportConfigSettingsSerializer, ExportDictDataSerializer, ExportDictDetailsSerializer, \
MessagePushSerializer, MessagePushCreateUpdateSerializer, ExportMessagePushSerializer, LoginInforSerializer MessagePushSerializer, MessagePushCreateUpdateSerializer, ExportMessagePushSerializer, LoginInforSerializer, \
OperationLogSerializer, ExportOperationLogSerializer
from ..utils.export_excel import export_excel_save_model from ..utils.export_excel import export_excel_save_model
from ..utils.response import SuccessResponse from ..utils.response import SuccessResponse
@ -224,3 +225,28 @@ class LoginInforModelViewSet(CustomModelViewSet):
filter_class = LoginInforFilter filter_class = LoginInforFilter
extra_filter_backends = [DataLevelPermissionsFilter] extra_filter_backends = [DataLevelPermissionsFilter]
ordering = 'create_datetime' # 默认排序 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="清空成功")

View File

@ -4,6 +4,7 @@ import traceback
from rest_framework import serializers, exceptions from rest_framework import serializers, exceptions
from rest_framework.views import set_rollback from rest_framework.views import set_rollback
from .request_util import get_verbose_name
from .response import ErrorResponse from .response import ErrorResponse
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -17,9 +18,9 @@ class APIException(Exception):
""" """
def __init__(self, code=201, message='API异常', args=('API异常',)): def __init__(self, code=201, message='API异常', args=('API异常',)):
self.args = args args = args
self.code = code code = code
self.message = message message = message
def __str__(self): def __str__(self):
return self.message return self.message
@ -36,7 +37,7 @@ class FrameworkException(Exception):
def __init__(self, message='框架异常', *args: object, **kwargs: object) -> None: def __init__(self, message='框架异常', *args: object, **kwargs: object) -> None:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.message = message message = message
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.message}" return f"{self.message}"
@ -64,6 +65,9 @@ def op_exception_handler(ex, context):
""" """
msg = '' msg = ''
code = '201' code = '201'
request = context.get('request')
request.session['model_name'] = get_verbose_name(view=context.get('view'))
if isinstance(ex, AuthenticationFailed): if isinstance(ex, AuthenticationFailed):
code = 401 code = 401
msg = ex.detail msg = ex.detail

View File

@ -172,3 +172,21 @@ def get_login_location(request, *args, **kwargs):
content = r.content.decode('GBK') content = r.content.decode('GBK')
return content.replace('\r', '').replace('\n', '') return content.replace('\r', '').replace('\n', '')
return "" 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 ""

View File

@ -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
})
}

View File

@ -98,6 +98,18 @@ export const constantRoutes = [
meta: { title: '字典数据', icon: '' } 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: '' }
}
]
} }
] ]

View File

@ -56,16 +56,13 @@ export function resetForm(refName) {
// 添加日期范围 // 添加日期范围
export function addDateRange(params, dateRange, propName) { export function addDateRange(params, dateRange, propName) {
var search = params; var search = params;
search.params = {};
if (null != dateRange && '' != dateRange) { if (null != dateRange && '' != dateRange) {
if (typeof(propName) === "undefined") { // create_datetime__range = this.dateRange
search.params["beginTime"] = dateRange[0]; var dateTime=new Date();
search.params["endTime"] = dateRange[1];
} else { search.as = JSON.stringify({create_datetime__range : dateRange});
search.params["begin" + propName] = dateRange[0];
search.params["end" + propName] = dateRange[1];
}
} }
console.log(11,search)
return search; return search;
} }

View File

@ -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>