mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-15 14:24:39 +00:00
Merge pull request #2641 from jumpserver/pr@dev@perf_activities_log
perf: 优化Activity日志[操作日志、登录日志]显示
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<Dialog
|
||||
v-if="logDetailVisible"
|
||||
v-if="detailVisible"
|
||||
:show-confirm="false"
|
||||
:show-cancel="false"
|
||||
:title="this.$tc('route.OperateLog')"
|
||||
:visible.sync="logDetailVisible"
|
||||
:title="title"
|
||||
:visible.sync="detailVisible"
|
||||
>
|
||||
<div>
|
||||
<div v-if="isEmpty()" style="text-align: center">
|
||||
@@ -12,24 +12,24 @@
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-table
|
||||
:data="row.diff"
|
||||
:data="diff"
|
||||
height="500"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
:label="this.$tc('audits.ChangeField')"
|
||||
prop="field"
|
||||
:prop="fieldName"
|
||||
show-overflow-tooltip
|
||||
width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="this.$tc('audits.BeforeChange')"
|
||||
prop="before"
|
||||
:prop="leftKeyName"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
:label="this.$tc('audits.AfterChange')"
|
||||
prop="after"
|
||||
:prop="rightKeyName"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
@@ -39,34 +39,45 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Dialog } from '@/components'
|
||||
import Dialog from '@/components/Dialog/index'
|
||||
|
||||
export default {
|
||||
name: 'DetailDialog',
|
||||
name: 'DiffDetail',
|
||||
components: {
|
||||
Dialog
|
||||
},
|
||||
props: {},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
},
|
||||
fieldName: {
|
||||
type: String,
|
||||
default: () => 'field'
|
||||
},
|
||||
leftKeyName: {
|
||||
type: String,
|
||||
default: () => 'before'
|
||||
},
|
||||
rightKeyName: {
|
||||
type: String,
|
||||
default: () => 'after'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
row: {
|
||||
diff: ''
|
||||
},
|
||||
logDetailVisible: false
|
||||
diff: '',
|
||||
detailVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isEmpty() {
|
||||
const content = this.row.diff
|
||||
const content = this.diff
|
||||
return !content || JSON.stringify(content) === '{}'
|
||||
},
|
||||
show(objId) {
|
||||
this.$axios.get(
|
||||
`/api/v1/audits/operate-logs/${objId}/?type=action_detail`,
|
||||
).then(res => {
|
||||
this.row.diff = res.diff
|
||||
this.logDetailVisible = true
|
||||
})
|
||||
show(data) {
|
||||
this.diff = data
|
||||
this.detailVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,40 @@
|
||||
<template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="12" :sm="24">
|
||||
<IBox :title="title" class="block" v-bind="$attrs">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(activity, index) in activities"
|
||||
:key="index"
|
||||
:size="activity.size"
|
||||
:timestamp="activity.timestamp"
|
||||
:type="activity.type"
|
||||
placement="bottom"
|
||||
>
|
||||
{{ activity.content }}
|
||||
<el-link v-if="activity.detail_url" type="primary" @click.native="onClick(activity.detail_url)">
|
||||
{{ $tc('common.Detail') }}
|
||||
</el-link>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</IBox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="12" :sm="24">
|
||||
<IBox :title="title" class="block" v-bind="$attrs">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(activity, index) in activities"
|
||||
:key="index"
|
||||
:size="activity.size"
|
||||
:timestamp="activity.timestamp"
|
||||
:type="activity.type"
|
||||
placement="bottom"
|
||||
>
|
||||
{{ activity.content }}
|
||||
<el-link v-if="activity.detail_url" type="primary" @click.native="onClick(activity.r_type, activity.detail_url)">
|
||||
{{ $tc('common.Detail') }}
|
||||
</el-link>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</IBox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<DiffDetail ref="DetailDialog" :title="this.$tc('route.OperateLog')" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IBox from '@/components/IBox'
|
||||
import DiffDetail from '@/components/Dialog/DiffDetail'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
|
||||
export default {
|
||||
name: 'ResourceActivity',
|
||||
components: {
|
||||
IBox
|
||||
IBox,
|
||||
DiffDetail
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
@@ -61,8 +66,16 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
onClick(taskUrl) {
|
||||
openTaskPage('', 'celery', taskUrl)
|
||||
onClick(type, taskUrl) {
|
||||
if (type === 'O') {
|
||||
this.$axios.get(taskUrl).then(
|
||||
res => {
|
||||
this.$refs.DetailDialog.show(res.diff)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
openTaskPage('', 'celery', taskUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,32 @@ export default [
|
||||
{
|
||||
path: 'login-logs',
|
||||
name: 'LoginLog',
|
||||
component: () => import('@/views/audits/LoginLogList'),
|
||||
component: empty,
|
||||
meta: {
|
||||
title: i18n.t('route.LoginLog'),
|
||||
permissions: ['audits.view_userloginlog']
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'LoginLogList',
|
||||
component: () => import('@/views/audits/LoginLog/LoginLogList'),
|
||||
meta: {
|
||||
title: i18n.t('route.LoginLog'),
|
||||
permissions: ['audits.view_userloginlog']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
name: 'LoginLogDetail',
|
||||
component: () => import('@/views/audits/LoginLog/LoginLogDetail/index'),
|
||||
hidden: true,
|
||||
meta: {
|
||||
title: i18n.t('route.LoginLog'),
|
||||
permissions: ['audits.view_userloginlog']
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'operate-logs',
|
||||
|
||||
39
src/views/audits/LoginLog/LoginLogDetail/Detail.vue
Normal file
39
src/views/audits/LoginLog/LoginLogDetail/Detail.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="14" :sm="24">
|
||||
<AutoDetailCard :url="url" :fields="detailFields" :object="object" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AutoDetailCard from '@/components/DetailCard/auto'
|
||||
|
||||
export default {
|
||||
name: 'Detail',
|
||||
components: {
|
||||
AutoDetailCard
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
url: `/api/v1/audits/login-logs/${this.object.id}`,
|
||||
detailFields: [
|
||||
'id', 'username', 'city', 'ip', 'backend_display', 'reason_display', 'status', 'type', 'user_agent', 'datetime'
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
49
src/views/audits/LoginLog/LoginLogDetail/index.vue
Normal file
49
src/views/audits/LoginLog/LoginLogDetail/index.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<GenericDetailPage
|
||||
:active-menu.sync="config.activeMenu"
|
||||
:object.sync="LogDetail"
|
||||
v-bind="config"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<keep-alive>
|
||||
<component :is="config.activeMenu" :object="LogDetail" />
|
||||
</keep-alive>
|
||||
</GenericDetailPage>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GenericDetailPage, TabPage } from '@/layout/components'
|
||||
import Detail from './Detail.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GenericDetailPage,
|
||||
TabPage,
|
||||
Detail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
LogDetail: {},
|
||||
config: {
|
||||
activeMenu: 'Detail',
|
||||
submenu: [
|
||||
{
|
||||
title: this.$t('common.BasicInfo'),
|
||||
name: 'Detail'
|
||||
}
|
||||
],
|
||||
actions: {
|
||||
hasUpdate: () => false,
|
||||
hasDelete: () => false
|
||||
},
|
||||
hasActivity: false,
|
||||
getObjectName: (obj) => { return obj.id }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
79
src/views/audits/LoginLog/LoginLogList.vue
Normal file
79
src/views/audits/LoginLog/LoginLogList.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<GenericListPage :header-actions="headerActions" :table-config="tableConfig" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListPage from '@/layout/components/GenericListPage'
|
||||
import { getDaysAgo, getDaysFuture } from '@/utils/common'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GenericListPage
|
||||
},
|
||||
data() {
|
||||
const now = new Date()
|
||||
const dateFrom = getDaysAgo(7, now).toISOString()
|
||||
const dateTo = getDaysFuture(1, now).toISOString()
|
||||
return {
|
||||
tableConfig: {
|
||||
permissions: {
|
||||
app: 'audits',
|
||||
resource: 'userloginlog'
|
||||
},
|
||||
columnsExclude: ['backend'],
|
||||
columnsShow: {
|
||||
min: ['username', 'type'],
|
||||
default: [
|
||||
'username', 'type', 'backend_display', 'ip', 'city',
|
||||
'user_agent', 'mfa', 'reason_display', 'status', 'datetime'
|
||||
]
|
||||
},
|
||||
url: '/api/v1/audits/login-logs/',
|
||||
columnsMeta: {
|
||||
user_agent: {
|
||||
width: '150px'
|
||||
},
|
||||
actions: {
|
||||
has: false
|
||||
},
|
||||
ip: {
|
||||
width: '140px'
|
||||
},
|
||||
city: {
|
||||
width: '90px'
|
||||
},
|
||||
mfa: {
|
||||
width: '80px'
|
||||
},
|
||||
type: {
|
||||
width: '110px'
|
||||
},
|
||||
datetime: {
|
||||
width: '160px'
|
||||
}
|
||||
},
|
||||
extraQuery: {
|
||||
date_to: dateTo,
|
||||
date_from: dateFrom
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasLeftActions: false,
|
||||
hasImport: false,
|
||||
hasDatePicker: true,
|
||||
datePicker: {
|
||||
dateStart: dateFrom,
|
||||
dateEnd: dateTo
|
||||
},
|
||||
searchConfig: {
|
||||
getUrlQuery: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -13,23 +13,21 @@
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<OperateLogDetailDialog
|
||||
ref="DetailDialog"
|
||||
/>
|
||||
<DiffDetail ref="DetailDialog" :title="this.$tc('route.OperateLog')" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { QuickActions } from '@/components'
|
||||
import AutoDetailCard from '@/components/DetailCard/auto'
|
||||
import OperateLogDetailDialog from './DetailDialog'
|
||||
import DiffDetail from '@/components/Dialog/DiffDetail'
|
||||
|
||||
export default {
|
||||
name: 'Detail',
|
||||
components: {
|
||||
QuickActions,
|
||||
AutoDetailCard,
|
||||
OperateLogDetailDialog
|
||||
DiffDetail
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
@@ -53,7 +51,11 @@ export default {
|
||||
},
|
||||
callbacks: {
|
||||
click: function() {
|
||||
this.$refs.DetailDialog.show(this.object.id)
|
||||
this.$axios.get(
|
||||
`api/v1/audits/operate-logs/${this.object.id}/?type=action_detail`
|
||||
).then(res => {
|
||||
this.$refs.DetailDialog.show(res.diff)
|
||||
})
|
||||
}.bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,23 +5,20 @@
|
||||
:header-actions="headerActions"
|
||||
:table-config="tableConfig"
|
||||
/>
|
||||
|
||||
<OperateLogDetailDialog
|
||||
ref="DetailDialog"
|
||||
/>
|
||||
<DiffDetail ref="DetailDialog" :title="this.$tc('route.OperateLog')" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListPage from '@/layout/components/GenericListPage'
|
||||
import { getDaysAgo, getDaysFuture } from '@/utils/common'
|
||||
import OperateLogDetailDialog from './OperateLogDetail/DetailDialog'
|
||||
import { ActionsFormatter } from '@/components/TableFormatters'
|
||||
import DiffDetail from '@/components/Dialog/DiffDetail'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GenericListPage,
|
||||
OperateLogDetailDialog
|
||||
DiffDetail
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
@@ -74,8 +71,13 @@ export default {
|
||||
type: 'primary',
|
||||
callback: ({ row }) => {
|
||||
vm.loading = true
|
||||
this.$refs.DetailDialog.show(row.id)
|
||||
vm.loading = false
|
||||
this.$axios.get(
|
||||
`api/v1/audits/operate-logs/${row.id}/?type=action_detail`
|
||||
).then(res => {
|
||||
this.$refs.DetailDialog.show(res.diff)
|
||||
}).finally(() => {
|
||||
vm.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user