mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-10 19:12:02 +00:00
Merge branch 'v4' of github.com:jumpserver/lina into v4
This commit is contained in:
commit
2d7fae677b
@ -52,10 +52,6 @@ export default {
|
|||||||
url: `/api/v1/perms/asset-permissions/${this.object.id}`,
|
url: `/api/v1/perms/asset-permissions/${this.object.id}`,
|
||||||
detailFields: [
|
detailFields: [
|
||||||
'name',
|
'name',
|
||||||
'users_amount',
|
|
||||||
'user_groups_amount',
|
|
||||||
'assets_amount',
|
|
||||||
'nodes_amount',
|
|
||||||
{
|
{
|
||||||
key: this.$t('Actions'),
|
key: this.$t('Actions'),
|
||||||
value: this.object.actions,
|
value: this.object.actions,
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row :gutter="20">
|
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||||
<el-col :md="16" :sm="24">
|
|
||||||
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row :gutter="20">
|
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
|
||||||
<el-col :md="16" :sm="24">
|
|
||||||
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -34,7 +30,7 @@ export default {
|
|||||||
width: '100px'
|
width: '100px'
|
||||||
},
|
},
|
||||||
is_success: {
|
is_success: {
|
||||||
width: '80px'
|
width: '100px'
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
width: '82px',
|
width: '82px',
|
||||||
|
@ -31,6 +31,9 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
|
is_success: {
|
||||||
|
width: '150px'
|
||||||
|
},
|
||||||
is_finished: {
|
is_finished: {
|
||||||
width: '150px',
|
width: '150px',
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
|
@ -42,25 +42,26 @@ export default {
|
|||||||
name: 'SessionCommands',
|
name: 'SessionCommands',
|
||||||
hidden: () => !this.$hasPerm('terminal.view_command')
|
hidden: () => !this.$hasPerm('terminal.view_command')
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('FileTransfer'),
|
|
||||||
name: 'SessionFTPLogs',
|
|
||||||
hidden: () => !this.$hasPerm('audits.view_ftplog')
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('Activity'),
|
title: this.$t('Activity'),
|
||||||
name: 'SessionJoinRecords',
|
name: 'SessionJoinRecords',
|
||||||
hidden: () => !this.$hasPerm('terminal.view_sessionjoinrecord')
|
hidden: () => !this.$hasPerm('terminal.view_sessionjoinrecord')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('FileTransfer'),
|
||||||
|
name: 'SessionFTPLogs',
|
||||||
|
hidden: () => !this.$hasPerm('audits.view_ftplog')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
getObjectName: (obj) => { return obj.id },
|
getObjectName: (obj) => {
|
||||||
|
return obj.id
|
||||||
|
},
|
||||||
hasActivity: true,
|
hasActivity: true,
|
||||||
hasRightSide: false
|
hasRightSide: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
74
src/views/settings/Terminal/ComponentLog/CardLog.vue
Normal file
74
src/views/settings/Terminal/ComponentLog/CardLog.vue
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<el-card class="log-card">
|
||||||
|
<div slot="header">
|
||||||
|
<span> {{ title }}</span>
|
||||||
|
<el-button style="float: right" type="text" @click="tailLog"> {{ $tc('TailLog') }} </el-button>
|
||||||
|
</div>
|
||||||
|
<table v-if="logs.length>0" class="log-table">
|
||||||
|
<tr v-for="(o,i) in logs" :key="i">
|
||||||
|
<td>{{ o['message'] }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table v-else class="log-table">
|
||||||
|
<tr>
|
||||||
|
<td>{{ $tc('NoLog') }}</td>
|
||||||
|
</tr>
|
||||||
|
</table></el-card>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { openWindow } from '@/utils/common'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CardLog',
|
||||||
|
props: {
|
||||||
|
logs: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
tailLog() {
|
||||||
|
const data = {
|
||||||
|
components: this.components.join('|'),
|
||||||
|
search: this.search
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams(data)
|
||||||
|
const url = '/ui/#/terminal/components/loki/tail/?' + params.toString()
|
||||||
|
openWindow(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.log-table {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow: scroll;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.log-table >>> td {
|
||||||
|
padding: 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-table >>> tr {
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.log-card >>> .el-card__body {
|
||||||
|
padding: 10px 10px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -2,22 +2,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<div :class="device" class="table-header clearfix">
|
<div :class="device" class="table-header clearfix">
|
||||||
<div class="search left">
|
<div class="search left">
|
||||||
<div class="search-input">
|
|
||||||
<el-select
|
|
||||||
v-model="selectComponents"
|
|
||||||
multiple
|
|
||||||
collapse-tags
|
|
||||||
:placeholder="$tc('Component')"
|
|
||||||
@change="selectChange"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in componentOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="search-input">
|
<div class="search-input">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="search"
|
v-model="search"
|
||||||
@ -40,77 +24,88 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<el-table
|
<div v-loading="loading" class="cards">
|
||||||
v-loading="loading"
|
<card-log
|
||||||
:data="componentLogs"
|
v-for="(card, index) in cardLogs"
|
||||||
>
|
:key="index"
|
||||||
<el-table-column
|
:components="card.components"
|
||||||
prop="component"
|
:title="card.title"
|
||||||
header-align="center"
|
:logs="card.logs"
|
||||||
align="center"
|
:search="isearch"
|
||||||
:label="$tc('Component')"
|
class="card-log"
|
||||||
width="120px"
|
/>
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="message"
|
|
||||||
align="left"
|
|
||||||
:label="$tc('Message')"
|
|
||||||
/>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import DatetimeRangePicker from '@/components/Form/FormFields/DatetimeRangePicker.vue'
|
import DatetimeRangePicker from '@/components/Form/FormFields/DatetimeRangePicker.vue'
|
||||||
import { getDaysAgo, getDaysFuture, openWindow } from '@/utils/common'
|
import { getDaysAgo, getDaysFuture } from '@/utils/common'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import { getLokiLog } from '@/api/component'
|
import { getLokiLog } from '@/api/component'
|
||||||
import ActionsGroup from '@/components/ActionsGroup'
|
import ActionsGroup from '@/components/ActionsGroup'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
import CardLog from './CardLog.vue'
|
||||||
const all_components = []
|
const all_components = []
|
||||||
const components_ce = [
|
const components_ce = [
|
||||||
'web', 'core', 'koko', 'lion', 'magnus', 'chen',
|
{
|
||||||
'jms_web', 'jms_core', 'jms_celery', 'jms_receptor', 'jms_koko', 'jms_lion', 'jms_chen'
|
'title': 'Core',
|
||||||
|
'components': ['core', 'jms_core']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Web',
|
||||||
|
'components': ['web', 'jms_web']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Koko',
|
||||||
|
'components': ['koko', 'jms_koko']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Lion',
|
||||||
|
'components': ['lion', 'jms_lion']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Chen',
|
||||||
|
'components': ['chen', 'jms_chen']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Magnus',
|
||||||
|
'components': ['magnus']
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const components_ee = [
|
const components_ee = [
|
||||||
'xrdp', 'razor',
|
{
|
||||||
'jms_razor', 'jms_xrdp'
|
'title': 'Razor',
|
||||||
|
'components': ['razor', 'jms_razor']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': 'Xrdp',
|
||||||
|
'components': ['xrdp', 'jms_xrdp']
|
||||||
|
}
|
||||||
]
|
]
|
||||||
all_components.push(...components_ce)
|
all_components.push(...components_ce)
|
||||||
store.getters.hasValidLicense ? all_components.push(...components_ee) : null
|
store.getters.hasValidLicense ? all_components.push(...components_ee) : null
|
||||||
all_components.sort((a, b) => {
|
|
||||||
if (a.startsWith('jms_') && !b.startsWith('jms_')) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
if (!a.startsWith('jms_') && b.startsWith('jms_')) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if (a.startsWith('jms_') && b.startsWith('jms_')) {
|
|
||||||
return a.replace('jms_', '').localeCompare(b.replace('jms_', ''))
|
|
||||||
}
|
|
||||||
return a.localeCompare(b)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ComponentLog',
|
name: 'ComponentLog',
|
||||||
components: {
|
components: {
|
||||||
DatetimeRangePicker,
|
DatetimeRangePicker,
|
||||||
ActionsGroup
|
ActionsGroup,
|
||||||
|
CardLog
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: true,
|
loading: true,
|
||||||
selectComponents: [],
|
|
||||||
componentNames: all_components,
|
|
||||||
search: '',
|
search: '',
|
||||||
isearch: '',
|
isearch: '',
|
||||||
datePicker: {
|
datePicker: {
|
||||||
dateStart: getDaysAgo(7).toISOString(),
|
dateStart: getDaysAgo(7).toISOString(),
|
||||||
dateEnd: getDaysFuture(1).toISOString()
|
dateEnd: getDaysFuture(1).toISOString()
|
||||||
},
|
},
|
||||||
lokiData: []
|
lokiData: [],
|
||||||
|
cards: all_components
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -122,13 +117,6 @@ export default {
|
|||||||
tip: this.$t('Refresh'),
|
tip: this.$t('Refresh'),
|
||||||
has: true,
|
has: true,
|
||||||
callback: this.refresh_component_logs.bind(this)
|
callback: this.refresh_component_logs.bind(this)
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'tailLog',
|
|
||||||
icon: 'file',
|
|
||||||
tip: this.$t('TailLog'),
|
|
||||||
has: this.selectComponents.length > 0,
|
|
||||||
callback: this.openTailLogWindow.bind(this)
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -138,36 +126,33 @@ export default {
|
|||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
},
|
},
|
||||||
componentLogs() {
|
cardLogs() {
|
||||||
const data = this.lokiData.map(item => {
|
const cards = this.cards.map(card => {
|
||||||
const component = item.stream['component']
|
return { title: card.title, components: card.components, logs: [] }
|
||||||
return item.values.map(value => {
|
})
|
||||||
return { component: this.component_label(component), time: value[0], message: value[1] }
|
this.lokiData.forEach(item => {
|
||||||
|
const componentName = item.stream['component']
|
||||||
|
const log = item.values.map(value => {
|
||||||
|
return { component: componentName, time: value[0], message: value[1] }
|
||||||
|
})
|
||||||
|
|
||||||
|
cards.forEach(card => {
|
||||||
|
if (card.components.includes(componentName)) {
|
||||||
|
card.logs = card.logs.concat(log)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return [].concat(...data)
|
// sort cards by logs length,the card with more logs will be displayed first
|
||||||
},
|
cards.sort((a, b) => {
|
||||||
componentOptions() {
|
return b.logs.length - a.logs.length
|
||||||
return this.componentNames.map(item => {
|
|
||||||
return {
|
|
||||||
value: item,
|
|
||||||
label: this.component_label(item)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
return cards
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.refresh_component_logs()
|
this.refresh_component_logs()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
component_label(item) {
|
|
||||||
let label = item
|
|
||||||
if (label.startsWith('jms_')) {
|
|
||||||
label = label.replace('jms_', '')
|
|
||||||
label = `${label}_stdout`
|
|
||||||
}
|
|
||||||
return label
|
|
||||||
},
|
|
||||||
handleDateChange: debounce(function(value) {
|
handleDateChange: debounce(function(value) {
|
||||||
this.datePicker = {
|
this.datePicker = {
|
||||||
dateStart: value[0].toISOString(),
|
dateStart: value[0].toISOString(),
|
||||||
@ -188,28 +173,17 @@ export default {
|
|||||||
const data = {
|
const data = {
|
||||||
start: Math.floor(startTime / 1000),
|
start: Math.floor(startTime / 1000),
|
||||||
end: Math.floor(endTime / 1000),
|
end: Math.floor(endTime / 1000),
|
||||||
search: this.isearch,
|
search: this.isearch
|
||||||
components: this.selectComponents.join('|')
|
|
||||||
}
|
}
|
||||||
this.loading = true
|
this.loading = true
|
||||||
getLokiLog(data)
|
getLokiLog(data)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.lokiData = response
|
this.lokiData = response
|
||||||
})
|
}).catch(error => {
|
||||||
.catch(error => {
|
this.$message.error(error)
|
||||||
console.log(error)
|
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
|
||||||
openTailLogWindow() {
|
|
||||||
const data = {
|
|
||||||
components: this.selectComponents.join('|'),
|
|
||||||
search: this.isearch
|
|
||||||
}
|
|
||||||
const params = new URLSearchParams(data)
|
|
||||||
const url = '/ui/#/terminal/components/loki/tail/?' + params.toString()
|
|
||||||
openWindow(url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,4 +277,7 @@ $headerHeight: 30px;
|
|||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.card-log {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user