dev-jingling
17602169347 9 months ago
parent dd44e01aec
commit 48926551e5

@ -1,7 +1,6 @@
# For Java
*.lck
target/
log/
logback-test.xml
@ -52,7 +51,6 @@ node_modules/
.buildpath
.settings
dist
npm-debug.log
nohup.out
_site
_data

@ -0,0 +1,28 @@
<template>
<BasicPopup v-bind="$attrs" @register="registerPopup" :title="title">
<BasicForm @register="registerForm" class="!px-10px" />
</BasicPopup>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicPopup, usePopupInner } from '/@/components/Popup';
import { BasicForm, useForm, FormSchema } from '/@/components/Form';
const title = ref('');
const schemas: FormSchema[] = [
{
field: 'value',
label: '',
component: 'Textarea',
componentProps: { placeholder: 'VALUE', rows: 33, readonly: true },
},
];
const [registerForm, { setFieldsValue, resetFields }] = useForm({ labelWidth: 50, schemas: schemas });
const [registerPopup] = usePopupInner(init);
function init(data) {
resetFields();
title.value = data.title;
setFieldsValue({ value: data.json });
}
</script>

@ -0,0 +1,236 @@
<template>
<div class="jnpf-content-wrapper">
<div class="jnpf-content-wrapper-center">
<div class="jnpf-content-wrapper-search-box">
<BasicForm @register="registerForm" @submit="handleSubmit" @reset="handleReset" />
</div>
<div class="jnpf-content-wrapper-content bg-white">
<a-tabs v-model:activeKey="activeKey" type="card" class="jnpf-content-wrapper-tabs" destroyInactiveTabPane>
<a-tab-pane key="1" tab="登录日志">
<BasicTable @register="registerLoginTable" :columns="loginTableColumns" :searchInfo="getSearchInfo">
<template #tableTitle>
<a-button type="error" preIcon="icon-ym icon-ym-btn-clearn" @click="handleDelete"></a-button>
<a-button type="link" danger @click="handleDelAll"></a-button>
</template>
</BasicTable>
</a-tab-pane>
<a-tab-pane key="5" tab="请求日志">
<BasicTable @register="registerRequestTable" :columns="requestTableColumns" :searchInfo="getSearchInfo">
<template #tableTitle>
<a-button type="error" preIcon="icon-ym icon-ym-btn-clearn" @click="handleDelete"></a-button>
<a-button type="link" danger @click="handleDelAll"></a-button>
</template>
</BasicTable>
</a-tab-pane>
<a-tab-pane key="3" tab="操作日志">
<BasicTable @register="registerOperationTable" :columns="operationTableColumns" :searchInfo="getSearchInfo">
<template #tableTitle>
<a-button type="error" preIcon="icon-ym icon-ym-btn-clearn" @click="handleDelete"></a-button>
<a-button type="link" danger @click="handleDelAll"></a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'json'">
<a :title="record.json" @click="handleView(record.json, '操作记录')">{{ record.json }}</a>
</template>
</template>
</BasicTable>
</a-tab-pane>
<a-tab-pane key="4" tab="异常日志">
<BasicTable @register="registerErrorTable" :columns="errorTableColumns" :searchInfo="getSearchInfo">
<template #tableTitle>
<a-button type="error" preIcon="icon-ym icon-ym-btn-clearn" @click="handleDelete"></a-button>
<a-button type="link" danger @click="handleDelAll"></a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'json'">
<a :title="record.json" @click="handleView(record.json, '异常描述')">{{ record.json }}</a>
</template>
</template>
</BasicTable>
</a-tab-pane>
</a-tabs>
</div>
</div>
<Form @register="registerDetailForm" />
</div>
</template>
<script lang="ts" setup>
import { reactive, toRefs, watch, onMounted, computed, nextTick } from 'vue';
import { getLogList, delLog, batchDelLog } from '/@/api/system/log';
import { BasicForm, useForm } from '/@/components/Form';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
import { usePopup } from '/@/components/Popup';
import Form from './Form.vue';
defineOptions({ name: 'system-log' });
interface State {
activeKey: string;
keyword: string;
startTime: number;
endTime: number;
}
const { createMessage, createConfirm } = useMessage();
const { t } = useI18n();
const state = reactive<State>({
activeKey: '1',
keyword: '',
startTime: 0,
endTime: 0,
});
const { activeKey } = toRefs(state);
const getSearchInfo = computed(() => ({ keyword: state.keyword, type: state.activeKey, startTime: state.startTime || null, endTime: state.endTime || null }));
const [registerForm] = useForm({
baseColProps: { span: 6 },
showActionButtonGroup: true,
showAdvancedButton: true,
compact: true,
labelAlign: 'left',
labelWidth: 60,
schemas: [
{
field: 'keyword',
label: t('common.keyword'),
component: 'Input',
componentProps: {
placeholder: t('common.enterKeyword'),
submitOnPressEnter: true,
},
},
{
field: 'pickerVal',
label: '开始时间',
component: 'DateRange',
},
],
fieldMapToTime: [['pickerVal', ['startTime', 'endTime']]],
});
const loginTableColumns: BasicColumn[] = [
{ title: '登录时间', dataIndex: 'creatorTime', width: 150, format: 'date|YYYY-MM-DD HH:mm' },
{ title: '登录用户', dataIndex: 'userName', width: 120 },
{ title: '登录IP', dataIndex: 'ipaddress', width: 120 },
{ title: '登录设备', dataIndex: 'platForm' },
];
const requestTableColumns: BasicColumn[] = [
{ title: '请求用户', dataIndex: 'userName', width: 120 },
{ title: '请求IP', dataIndex: 'ipaddress', width: 120 },
{ title: '请求设备', dataIndex: 'platForm', width: 200 },
{ title: '请求地址', dataIndex: 'requestURL', width: 200 },
{ title: '请求类型', dataIndex: 'requestMethod', width: 80, align: 'center' },
{ title: '耗时(毫秒)', dataIndex: 'requestDuration', width: 100 },
];
const operationTableColumns: BasicColumn[] = [
{ title: '操作时间', dataIndex: 'creatorTime', width: 150, format: 'date|YYYY-MM-DD HH:mm' },
{ title: '操作用户', dataIndex: 'userName', width: 120 },
{ title: '操作IP', dataIndex: 'ipaddress', width: 160 },
{ title: '操作模块', dataIndex: 'moduleName', width: 80 },
{ title: '操作类型', dataIndex: 'requestMethod', width: 80, align: 'center' },
{ title: '耗时(毫秒)', dataIndex: 'requestDuration', width: 100 },
{ title: '操作记录', dataIndex: 'json', maxWidth: 200 },
];
const errorTableColumns: BasicColumn[] = [
{ title: '创建时间', dataIndex: 'creatorTime', width: 150, format: 'date|YYYY-MM-DD HH:mm' },
{ title: '创建用户', dataIndex: 'userName', width: 120 },
{ title: '异常IP', dataIndex: 'ipaddress', width: 120 },
{ title: '异常功能', dataIndex: 'moduleName', width: 120 },
{ title: '异常描述', dataIndex: 'json' },
];
const [registerLoginTable, { reload: reloadLoginTable, getSelectRows: getLoginSelectRows }] = useTable({
api: getLogList,
rowSelection: { type: 'checkbox' },
immediate: false,
clickToRowSelect: false,
});
const [registerRequestTable, { reload: reloadRequestTable, getSelectRows: getRequestSelectRows }] = useTable({
api: getLogList,
rowSelection: { type: 'checkbox' },
immediate: false,
clickToRowSelect: false,
});
const [registerOperationTable, { reload: reloadOperationTable, getSelectRows: getOperationSelectRows }] = useTable({
api: getLogList,
rowSelection: { type: 'checkbox' },
immediate: false,
clickToRowSelect: false,
});
const [registerErrorTable, { reload: reloadErrorTable, getSelectRows: getErrorSelectRows }] = useTable({
api: getLogList,
rowSelection: { type: 'checkbox' },
immediate: false,
clickToRowSelect: false,
});
const [registerDetailForm, { openPopup: openFormPopup }] = usePopup();
watch(
() => state.activeKey,
() => {
nextTick(() => reload());
},
);
function handleSubmit(values) {
state.keyword = values?.keyword || '';
state.startTime = values?.startTime || 0;
state.endTime = values?.endTime || 0;
handleSearch();
}
function handleReset() {
state.keyword = '';
state.startTime = 0;
state.endTime = 0;
handleSearch();
}
function handleSearch() {
nextTick(() => {
reload();
});
}
function handleDelete() {
const list: any[] = getSelectData() || [];
if (!list.length) return createMessage.error('请选择一条数据');
const query = {
ids: list.map(item => item.id),
};
delLog(query).then(res => {
createMessage.success(res.msg);
reload();
});
}
function handleDelAll() {
createConfirm({
iconType: 'warning',
title: t('common.tipTitle'),
content: '此操作会将所有日志删除,是否继续?',
onOk: () => {
batchDelLog(state.activeKey).then(res => {
createMessage.success(res.msg);
reload();
});
},
});
}
function handleView(json, title) {
openFormPopup(true, { json, title });
}
function reload() {
if (state.activeKey === '1') reloadLoginTable({ page: 1 });
if (state.activeKey === '5') reloadRequestTable({ page: 1 });
if (state.activeKey === '3') reloadOperationTable({ page: 1 });
if (state.activeKey === '4') reloadErrorTable({ page: 1 });
}
function getSelectData() {
if (state.activeKey === '1') return getLoginSelectRows();
if (state.activeKey === '5') return getRequestSelectRows();
if (state.activeKey === '3') return getOperationSelectRows();
if (state.activeKey === '4') return getErrorSelectRows();
}
onMounted(() => {
reload();
});
</script>

@ -1,7 +1,6 @@
# Compiled class file
*.class
# Log file
# BlueJ files
*.ctxt
@ -45,7 +44,6 @@ Thumbs.db
node_modules/
.buildpath
.settings
npm-debug.log
nohup.out
_site
_data

@ -0,0 +1,209 @@
<template>
<div class="popupSelect-container">
<el-dialog title="日志详情" :close-on-click-modal="false" :visible.sync="visible"
class="JNPF-dialog JNPF-dialog_center log-detail-modal" lock-scroll append-to-body
width="800px">
<div class="log-detail-board" v-loading="listLoading">
<div class="log-left-board">
<div class="item-box" :class="{ active: activeItem.id == item.id }"
v-for="(item, index) in list" @click="handleClick(item,index)" :key='item.id'>
<div class="top">
<span class="fullName">{{ item.nodeName }}</span>
<i class="icon icon-ym icon-ym-fail" v-if="!item.resultType" />
<i class="icon icon-ym icon-ym-success" v-else />
</div>
<div class="bottom">
<i class="icon-ym icon-ym-clock pr-4px" v-if="item.type == 1" />
<i class="icon-ym icon-ym-btn-refresh pr-4px" v-else />
{{ item.endTime|toDate('yyyy-MM-dd HH:mm') }}
</div>
</div>
</div>
<div class="log-center-board">
<div class="top">
<span>{{ activeItem.nodeName }}</span>
<div v-if="!activeItem.resultType">
<el-button @click="handleUpdateNodes"></el-button>
<el-button @click="handleRedoNodes" :disabled="!activeItem.isRetry"
:loading="redoNodesLoading">
{{ redoNodesLoading ? '正在修复中...' : '节点重试' }}</el-button>
</div>
</div>
<div class="time-box">
<span>开始时间{{ activeItem.startTime|toDate('yyyy-MM-dd HH:mm') }}</span>
<span>结束时间{{ activeItem.endTime|toDate('yyyy-MM-dd HH:mm') }}</span>
</div>
<el-radio-group v-model="activeKey" class="mb-10px">
<el-radio-button :label="1">输入</el-radio-button>
<el-radio-button :label="2" v-if="!activeItem.resultType"></el-radio-button>
</el-radio-group>
<el-input v-model="getTextareaValue" type="textarea"
:autosize="{ minRows: 19, maxRows: 19}" readonly />
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { getTaskInfo, nodeRetryTask } from '@/api/onlineDev/integrate'
export default {
name: 'LogDetail',
model: {
prop: 'value',
event: 'input'
},
data() {
return {
list: [],
activeKey: 1,
activeItem: {},
visible: false,
msgInfo: '',
id: '',
listLoading: false,
redoNodesLoading: false,
activeIndex: 0
}
},
computed: {
getTextareaValue() {
return this.activeKey === 1 ? this.msgInfo : this.activeItem.errorMsg
}
},
methods: {
openDialog(id) {
this.visible = true
this.id = id || ''
this.isInit = false
this.activeKey = 1
this.initData(true)
},
handleClick(item, index) {
this.activeItem = item;
this.activeIndex = index;
this.activeKey = 1;
},
handleUpdateNodes() {
this.$emit('updateNodes')
},
handleRedoNodes() {
this.$confirm('确定将本节点进行重试?', this.$t('common.tipTitle'), {
type: 'warning'
}).then(() => {
const query = {
id: this.id,
nodeId: this.activeItem.id,
};
this.redoNodesLoading = true;
nodeRetryTask(query).then(res => {
this.$message({
type: 'success',
message: res.msg,
duration: 1000,
onClose: () => {
this.initData()
this.redoNodesLoading = false;
}
});
})
}).catch(() => {
this.redoNodesLoading = false;
});
},
initData(isInit) {
this.listLoading = true
getTaskInfo(this.id).then(res => {
this.msgInfo = res.data.data
this.list = res.data.list || []
if (this.list.length) this.activeItem = this.list[isInit ? 0 : this.activeIndex]
this.listLoading = false
}).catch()
}
}
}
</script>
<style lang="scss" scoped>
.log-detail-modal {
>>> .el-dialog__body {
padding: 0 !important;
}
.log-detail-board {
display: flex;
height: 550px;
.log-left-board {
width: 270px;
height: 100%;
overflow-y: auto;
border-right: 1px solid #d9d9d9;
.active {
background-color: #bae7ff !important;
}
.item-box {
padding: 8px 20px;
cursor: pointer;
&:hover {
background-color: #f5f5f5;
}
.top {
display: flex;
align-items: center;
.fullName {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 16px;
}
.icon {
width: 28px;
height: 28px;
border-radius: 50%;
padding: 5px;
text-align: center;
color: #fff;
transform: scale(0.65);
}
.icon-ym-fail {
background-color: #ff4d4d;
}
.icon-ym-success {
background-color: #55d187;
}
}
.bottom {
display: flex;
align-items: center;
.icon-ym-btn-refresh {
color: #1890ff;
}
}
.pr-4px {
padding-right: 4px;
}
}
}
.log-center-board {
width: 100%;
padding: 15px 20px;
.top {
display: flex;
align-items: center;
justify-content: space-between;
}
.time-box {
padding: 20px 0;
display: flex;
span {
flex: 1;
}
}
.mb-10px {
margin-bottom: 10px !important;
}
}
}
}
</style>

@ -0,0 +1,235 @@
<template>
<transition name="el-zoom-in-center">
<div class="JNPF-preview-main">
<div class="JNPF-common-page-header">
<el-page-header @back="goBack()" :content="title" />
<div class="options">
<el-button @click="goBack()">{{$t('common.cancelButton')}}</el-button>
</div>
</div>
<div class="main">
<el-row class="JNPF-common-search-box" :gutter="16">
<el-form @submit.native.prevent>
<el-col :span="6">
<el-form-item label="执行时间">
<el-date-picker v-model="pickerVal" type="daterange" start-placeholder=""
end-placeholder="结束日期" :picker-options="pickerOptions" value-format="timestamp"
clearable :editable="false" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="执行结果">
<el-select v-model="listQuery.resultType" placeholder="请选择执行结果" clearable>
<el-option label="成功" :value="1" />
<el-option label="失败" :value="0" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="search()">
{{$t('common.search')}}</el-button>
<el-button icon="el-icon-refresh-right" @click="reset()">{{$t('common.reset')}}
</el-button>
</el-form-item>
</el-col>
</el-form>
</el-row>
<JNPF-table v-loading="listLoading" :data="list">
<el-table-column prop="processId" label="实例ID" min-width="300" show-overflow-tooltip>
<template slot-scope="scope">
<template v-if="scope.row.isRetry">
<span>{{ scope.row.processId }}</span><span>{{'&nbsp;'}}</span><el-tag
type="primary" disable-transitions>
重试</el-tag><span>{{'&nbsp;'}}</span><span>
<el-tooltip class="item" effect="dark" placement="top">
<div slot="content">
原实例ID{{ scope.row.parentId }}<br />原实例执行时间{{ scope.row.parentTime|toDate('yyyy-MM-dd HH:mm')}}
</div>
<i class="icon-ym icon-ym-generator-link cursor-pointer" />
</el-tooltip>
</span>
</template>
<template v-else>{{ scope.row.processId }}</template>
</template>
</el-table-column>
<el-table-column prop="resultType" label="执行结果" width="150">
<template slot-scope="scope">
<el-tag :type="scope.row.resultType == 1 ? 'success':'danger'" disable-transitions>
{{scope.row.resultType==1?'成功':'失败'}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="executionTime" label="执行时间 " :formatter="jnpf.tableDateFormat"
width="200" />
<el-table-column label="操作" fixed="right" width="150">
<template slot-scope="scope">
<el-button size="mini" type="text" @click="Detail(scope.row.id)">
详情</el-button>
<el-button size="mini" type="text" class="JNPF-table-delBtn"
@click="handleDetail(scope.row.id)">
删除</el-button>
<el-button size="mini" type="text" v-if="scope.row.resultType!=1"
@click="handleRedo(scope.row.id)">
重试</el-button>
</template>
</el-table-column>
</JNPF-table>
<pagination :total="total" :page.sync="listQuery.currentPage"
:limit.sync="listQuery.pageSize" @pagination="initData" />
</div>
<Detail v-if="detailVisible" ref="Detail" @updateNodes='updateNodes'></Detail>
</div>
</transition>
</template>
<script>
import { getTaskList, retryTask, delTask } from '@/api/onlineDev/integrate'
import Detail from './Detail'
export default {
components: { Detail },
data() {
return {
integrateId: '',
title: '',
list: [],
total: 0,
listLoading: false,
listQuery: {
resultType: '',
startTime: '',
endTime: '',
currentPage: 1,
pageSize: 20,
sort: 'desc',
},
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}]
},
pickerVal: [],
detailVisible: false
}
},
methods: {
goBack() {
this.$emit('close')
},
Detail(id) {
this.detailVisible = true
this.$nextTick(() => {
this.$refs.Detail.openDialog(id)
})
},
updateNodes() {
this.$emit('updateNodes', this.integrateId);
this.goBack()
},
handleDetail(id) {
this.$confirm('确定将本实例进行删除?', this.$t('common.tipTitle'), {
type: 'warning'
}).then(() => {
delTask(id).then(res => {
this.$message({
type: 'success',
message: res.msg,
duration: 1000,
onClose: () => {
this.initData()
}
});
})
}).catch(() => { });
},
handleRedo(id) {
this.$confirm('确定将本实例进行重试?', this.$t('common.tipTitle'), {
type: 'warning'
}).then(() => {
retryTask(id).then(res => {
this.$message({
type: 'success',
message: res.msg,
duration: 1000,
onClose: () => {
this.initData()
}
});
})
}).catch(() => { });
},
init(data) {
this.integrateId = data.id
this.title = data.fullName
this.initData()
},
initData() {
this.listLoading = true
let query = {
...this.listQuery,
integrateId: this.integrateId
}
getTaskList(query).then(res => {
this.list = res.data.list
this.total = res.data.pagination.total
})
this.listLoading = false
},
search() {
if (this.pickerVal && this.pickerVal.length) {
this.listQuery.startTime = this.pickerVal[0]
this.listQuery.endTime = this.pickerVal[1]
} else {
this.listQuery.startTime = ''
this.listQuery.endTime = ''
}
this.listQuery.currentPage = 1
this.listQuery.pageSize = 20
this.listQuery.sort = 'desc'
this.initData()
},
reset() {
this.pickerVal = []
this.listQuery.resultType = ''
this.search()
},
}
}
</script>
<style lang="scss" scoped>
.main {
overflow: hidden;
display: flex;
flex-direction: column;
padding: 0 0 10px;
>>> .el-table {
flex: 1;
border-top: none;
}
}
.cursor-pointer {
cursor: pointer;
}
</style>

@ -0,0 +1,58 @@
<template>
<transition name="el-zoom-in-center">
<div class="JNPF-preview-main">
<div class="JNPF-common-page-header">
<el-page-header @back="goBack" :content="title" />
<div class="options">
<el-button @click="goBack()">{{$t('common.cancelButton')}}</el-button>
</div>
</div>
<el-form label-width="100px" class="main">
<el-form-item label-width="0" class="value-item">
<el-input v-model="data" type="textarea" :rows="30" />
</el-form-item>
</el-form>
</div>
</transition>
</template>
<script>
export default {
data() {
return {
visible: false,
data: '',
title: '异常描述'
}
},
methods: {
init(data, title) {
this.data = data || ''
this.title = title
this.visible = true
},
goBack() {
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.main {
display: flex;
flex-direction: column;
.value-item {
flex: 1;
margin-bottom: 0;
>>> .el-form-item__content {
height: 100%;
.el-textarea {
height: 100%;
.el-textarea__inner {
height: 100%;
}
}
}
}
}
</style>

@ -0,0 +1,289 @@
<template>
<div class="JNPF-common-layout systemLogs">
<div class="JNPF-common-layout-center">
<el-row class="JNPF-common-search-box" :gutter="16">
<el-form @submit.native.prevent>
<el-col :span="6">
<el-form-item label="关键词">
<el-input v-model="listQuery.keyword" placeholder="请输入关键词查询" clearable
@keyup.enter.native="search()" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="时间">
<el-date-picker v-model="pickerVal" type="daterange" start-placeholder=""
end-placeholder="结束日期" :picker-options="pickerOptions" value-format="timestamp"
clearable :editable="false" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="search()">
{{$t('common.search')}}</el-button>
<el-button icon="el-icon-refresh-right" @click="reset()">{{$t('common.reset')}}
</el-button>
</el-form-item>
</el-col>
</el-form>
</el-row>
<div class="JNPF-common-layout-main JNPF-flex-main">
<el-tabs v-model="activeName" type="border-card" class="logTabs"
@tab-click="handleTabClick">
<div class="JNPF-common-head">
<div class="left-btn">
<el-button type="danger" size="small" @click="handleDel" icon="el-icon-delete">删除
</el-button>
<el-link type="danger" :underline="false" @click="batchDel" style="margin-left:10px">
一键清空</el-link>
</div>
<div class="JNPF-common-head-right">
<el-tooltip effect="dark" :content="$t('common.refresh')" placement="top">
<el-link icon="icon-ym icon-ym-Refresh JNPF-common-head-icon" :underline="false"
@click="initData()" />
</el-tooltip>
</div>
</div>
<el-tab-pane label="登录日志" name="1">
<JNPF-table v-loading="listLoading" :data="loginLogData" has-c
@selection-change="handleSelectionChange">
<el-table-column prop="creatorTime" :formatter="jnpf.tableDateFormat" label="登录时间"
width="120" />
<el-table-column prop="userName" label="登录用户" width="120" />
<el-table-column prop="ipaddress" label="登录IP" width="120" />
<el-table-column prop="platForm" label="登录设备" show-overflow-tooltip />
</JNPF-table>
</el-tab-pane>
<el-tab-pane label="请求日志" name="5">
<JNPF-table v-loading="listLoading" :data="requestLogData" has-c
@selection-change="handleSelectionChange">
<el-table-column prop="creatorTime" :formatter="jnpf.tableDateFormat" label="请求时间"
width="120" />
<el-table-column prop="userName" label="请求用户" width="120" />
<el-table-column prop="ipaddress" label="请求IP" width="120" />
<el-table-column prop="platForm" label="请求设备" min-width="200" show-overflow-tooltip />
<el-table-column prop="requestURL" label="请求地址" min-width="200"
show-overflow-tooltip />
<el-table-column prop="requestMethod" label="请求类型" width="80" align="center" />
<el-table-column prop="requestDuration" label="耗时(毫秒)" width="80" />
</JNPF-table>
</el-tab-pane>
<el-tab-pane label="操作日志" name="3">
<JNPF-table v-loading="listLoading" :data="operationLogData" has-c
@selection-change="handleSelectionChange">
<el-table-column prop="creatorTime" :formatter="jnpf.tableDateFormat" label="操作时间"
width="120" />
<el-table-column prop="userName" label="操作用户" width="120" />
<el-table-column prop="ipaddress" label="操作IP" width="120" />
<el-table-column prop="moduleName" label="操作模块" width="160" />
<el-table-column prop="requestMethod" label="操作类型" width="80" align="center" />
<el-table-column prop="requestDuration" label="耗时(毫秒)" width="80" />
<el-table-column prop="json" label="操作记录" min-width="200">
<template slot-scope="scope">
<el-link @click="goDetail(scope.row.json,'操作记录')" style="font-size:12px">
<p class="line1">{{ scope.row.json }}</p>
</el-link>
</template>
</el-table-column>
</JNPF-table>
</el-tab-pane>
<el-tab-pane label="异常日志" name="4">
<JNPF-table v-loading="listLoading" :data="errorLogData" has-c
@selection-change="handleSelectionChange">
<el-table-column prop="creatorTime" :formatter="jnpf.tableDateFormat" label="创建时间"
width="120" />
<el-table-column prop="userName" label="创建用户" width="120" />
<el-table-column prop="ipaddress" label="异常IP" width="120" />
<el-table-column prop="moduleName" label="异常功能" width="120" />
<el-table-column prop="json" label="异常描述" min-width="200">
<template slot-scope="scope">
<el-link @click="goDetail(scope.row.json,'异常描述')" style="font-size:12px">
<p class="line1">{{ scope.row.json }}</p>
</el-link>
</template>
</el-table-column>
</JNPF-table>
</el-tab-pane>
<pagination :total="total" :page.sync="listQuery.currentPage"
:limit.sync="listQuery.pageSize" @pagination="initData" />
</el-tabs>
</div>
</div>
<Form v-show="formVisible" ref="Form" @close="formVisible=false" />
</div>
</template>
<script>
import { getLogList, delLog, batchDelLog } from '@/api/system/log'
import Form from './Form'
export default {
name: 'system-log',
components: { Form },
data() {
return {
formVisible: false,
listLoading: true,
activeName: '1',
loginLogData: [],
errorLogData: [],
requestLogData: [],
operationLogData: [],
multipleSelection: [],
total: 0,
listQuery: {
keyword: '',
startTime: '',
endTime: '',
sort: 'desc',
currentPage: 1,
pageSize: 20
},
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick(picker) {
const start = new Date()
const end = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}]
},
pickerVal: []
}
},
created() {
this.initData()
},
methods: {
initData() {
const activeId = this.activeName
this.listLoading = true
getLogList(activeId, this.listQuery).then(res => {
if (activeId === '1') this.loginLogData = res.data.list
if (activeId === '3') this.operationLogData = res.data.list
if (activeId === '4') this.errorLogData = res.data.list
if (activeId === '5') this.requestLogData = res.data.list
this.total = res.data.pagination.total
this.listLoading = false
}).catch(() => {
this.listLoading = false
})
},
handleTabClick() {
this.reset()
},
goDetail(data, title) {
this.formVisible = true
this.$nextTick(() => {
this.$refs.Form.init(data, title)
})
},
handleSelectionChange(val) {
const res = val.map(item => item.id)
this.multipleSelection = res
},
handleDel() {
if (!this.multipleSelection.length) {
this.$message({
type: 'error',
message: '请选择一条数据',
duration: 1500,
})
return
}
const data = {
ids: this.multipleSelection
}
this.$confirm('您确定要删除这些数据吗, 是否继续?', '提示', {
type: 'warning'
}).then(() => {
delLog(data).then(res => {
this.$message({
type: 'success',
message: res.msg,
duration: 1500,
onClose: () => {
this.initData()
}
})
})
}).catch(() => { })
},
batchDel() {
this.$confirm('此操作会将所有日志删除,是否继续?', '提示', {
type: 'warning'
}).then(() => {
batchDelLog(this.activeName).then(res => {
this.$message({
type: 'success',
message: res.msg,
duration: 1500,
onClose: () => {
this.initData()
}
})
})
}).catch(() => { })
},
search() {
if (this.pickerVal && this.pickerVal.length) {
this.listQuery.startTime = this.pickerVal[0]
this.listQuery.endTime = this.pickerVal[1]
} else {
this.listQuery.startTime = ''
this.listQuery.endTime = ''
}
this.listQuery.currentPage = 1
this.listQuery.pageSize = 20
this.listQuery.sort = 'desc'
this.initData()
},
reset() {
this.pickerVal = []
this.listQuery.keyword = ''
this.search()
}
}
}
</script>
<style lang="scss" scoped>
.systemLogs {
.JNPF-common-layout-main {
padding: 0;
}
.logTabs {
height: 100%;
}
.line1 {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
}
>>> .el-tabs__content {
height: calc(100% - 40px);
padding: 0;
.el-tab-pane {
height: calc(100% - 110px);
overflow: hidden;
}
}
}
</style>
Loading…
Cancel
Save