mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-18 16:32:28 +00:00
perf: 任务列表优化
This commit is contained in:
@@ -669,6 +669,7 @@
|
||||
"selectedAssets": "已选择资产:",
|
||||
"stat": "成功/失败/总",
|
||||
"success": "成功",
|
||||
"total": "总共",
|
||||
"taskDetail": "任务详情",
|
||||
"taskName": "任务名称",
|
||||
"taskVersions": "任务各版本",
|
||||
@@ -692,7 +693,10 @@
|
||||
"myAdhoc": "我的命令",
|
||||
"history": "历史记录",
|
||||
"createAdhoc": "创建命令",
|
||||
"AdhocDetail": "命令详情"
|
||||
"AdhocDetail": "命令详情",
|
||||
"Queue": "队列",
|
||||
"State": "状态",
|
||||
"LastPublishedTime": "最后发布时间"
|
||||
},
|
||||
"perms": {
|
||||
"": "",
|
||||
|
@@ -1,56 +0,0 @@
|
||||
<template>
|
||||
<IBox :fa="icon" :type="type" :title="title" v-bind="$attrs">
|
||||
<table class="run-info">
|
||||
<p v-if="contents.length === 0">{{ $t('common.Nothing') }}</p>
|
||||
<tr v-for="content in contents" :key="content.hostname">
|
||||
<td>{{ content.hostname }}</td>
|
||||
<td>{{ content.result }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</IBox>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IBox from '@/components/IBox'
|
||||
|
||||
export default {
|
||||
name: 'RunInfoCard',
|
||||
components: {
|
||||
IBox
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contents: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.run-info {
|
||||
line-height: 1.43;
|
||||
padding: 8px;
|
||||
vertical-align: top;
|
||||
font-size: 13px;
|
||||
}
|
||||
.run-info > tr:first-child > td:first-child {
|
||||
width: 150px;
|
||||
}
|
||||
</style>
|
@@ -1,95 +0,0 @@
|
||||
<template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="14" :sm="24">
|
||||
<DetailCard :title="cardTitle" :items="detailCardItems" />
|
||||
</el-col>
|
||||
<el-col :md="10" :sm="24">
|
||||
<RunInfoCard type="danger" style="margin-top: 15px" v-bind="RunFailedConfig" />
|
||||
<RunInfoCard type="info" v-bind="RunSuccessConfig" style="margin-top: 15px" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script type="text/jsx">
|
||||
import DetailCard from '@/components/DetailCard'
|
||||
import { toSafeLocalDateStr } from '@/utils/common'
|
||||
import RunInfoCard from '../../../tasks/RunInfoCard'
|
||||
import { toLastFailureDisplay, toLastSucessDisplay } from '../business'
|
||||
import { openTaskPage } from '@/utils/jms'
|
||||
|
||||
export default {
|
||||
name: 'HistoryExecutionDetail',
|
||||
components: {
|
||||
DetailCard,
|
||||
RunInfoCard
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
RunSuccessConfig: {
|
||||
icon: 'fa-info',
|
||||
title: this.$t('ops.lastRunSuccessHosts'),
|
||||
contents: toLastSucessDisplay(this.object)
|
||||
},
|
||||
RunFailedConfig: {
|
||||
icon: 'fa-info',
|
||||
title: this.$t('ops.lastRunFailedHosts'),
|
||||
contents: toLastFailureDisplay(this.object)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cardTitle() {
|
||||
return `${this.object.task_display.replace('@', ':')}${this.object.adhoc_short_id}`
|
||||
},
|
||||
detailCardItems() {
|
||||
return [
|
||||
{
|
||||
key: this.$t('ops.taskName'),
|
||||
value: this.object.task_display.replace('@', '')
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.version'),
|
||||
value: this.object.adhoc_short_id
|
||||
},
|
||||
{
|
||||
key: this.$t('common.DateStart'),
|
||||
value: toSafeLocalDateStr(this.object.date_start)
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.timeDelta'),
|
||||
value: this.object.timedelta.toFixed(2) + 's'
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.isFinished'),
|
||||
value: this.object.is_finished
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.isSuccess'),
|
||||
value: this.object.is_success
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.output'),
|
||||
value: this.object.id,
|
||||
formatter: function(row, value) {
|
||||
const onClick = function() {
|
||||
openTaskPage(value, 'ansible')
|
||||
}
|
||||
const title = this.$t('common.View')
|
||||
return <a onClick={onClick} >{ title }</a>
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
@@ -1,45 +0,0 @@
|
||||
<template>
|
||||
<GenericDetailPage :object.sync="HistoryExecutionDetail" :active-menu.sync="config.activeMenu" v-bind="config" v-on="$listeners">
|
||||
<keep-alive>
|
||||
<component :is="config.activeMenu" :object="HistoryExecutionDetail" />
|
||||
</keep-alive>
|
||||
</GenericDetailPage>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GenericDetailPage, TabPage } from '@/layout/components'
|
||||
import HistoryExecutionDetail from './HistoryExecutionDetail'
|
||||
import CeleryTaskLog from '../../CeleryTaskLog'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HistoryExecutionDetail,
|
||||
GenericDetailPage,
|
||||
CeleryTaskLog,
|
||||
TabPage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
HistoryExecutionDetail: {},
|
||||
config: {
|
||||
activeMenu: 'HistoryExecutionDetail',
|
||||
title: this.$t('ops.executionDetail'),
|
||||
submenu: [
|
||||
{
|
||||
title: this.$t('ops.executionDetail'),
|
||||
name: 'HistoryExecutionDetail'
|
||||
}
|
||||
],
|
||||
hasRightSide: false,
|
||||
actions: {
|
||||
detailApiUrl: `/api/v1/ops/adhoc-executions/${this.$route.params.id}/`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@@ -32,6 +32,18 @@ export default {
|
||||
{
|
||||
key: this.$t('common.Name'),
|
||||
value: this.object.name
|
||||
},
|
||||
{
|
||||
key: this.$t('common.Comment'),
|
||||
value: this.object.meta.comment
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.Queue'),
|
||||
value: this.object.meta.queue
|
||||
},
|
||||
{
|
||||
key: this.$t('ops.LastPublishedTime'),
|
||||
value: this.object.last_published_time
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -21,23 +21,11 @@ export default {
|
||||
tableConfig: {
|
||||
url: `/api/v1/ops/task-executions/?task_id=${this.object.id}`,
|
||||
columns: [
|
||||
'id', 'state', 'is_finished', 'date_published', 'date_start', 'date_finished', 'actions'
|
||||
'date_start', 'date_finished', 'state', 'is_finished', 'actions'
|
||||
],
|
||||
columnsMeta: {
|
||||
state: {
|
||||
label: this.$t('ops.state'),
|
||||
width: '120px',
|
||||
formatter: (row) => {
|
||||
switch (row.state) {
|
||||
case 'PENDING':
|
||||
return <span><i Class='fa fa-spinner fa-spin' />{this.$t(`ops.${row.state}`)}</span>
|
||||
case 'RUNNING':
|
||||
return <span><i Class='fa fa-spinner fa-spin' />{this.$t(`ops.${row.state}`)}</span>
|
||||
case 'SUCCESS':
|
||||
return <span Class='text-success'><i Class='fa fa-check' />{this.$t(`ops.${row.state}`)}</span>
|
||||
case 'FAILURE':
|
||||
return <span Class='text-danger'><i Class='fa fa-times' />{this.$t(`ops.${row.state}`)}</span>
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
@@ -1,36 +0,0 @@
|
||||
|
||||
export const toLastSucessDisplay = function(object) {
|
||||
const last_success = object && object.last_success
|
||||
|
||||
if (!(last_success instanceof Array)) return []
|
||||
return last_success.map(host => {
|
||||
return {
|
||||
hostname: host,
|
||||
result: ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const toLastFailureDisplay = function(object) {
|
||||
const last_failure = object && object.last_failure
|
||||
if (!(last_failure instanceof Object)) return []
|
||||
|
||||
const ret = []
|
||||
|
||||
for (const host in last_failure) {
|
||||
const task = last_failure[host]
|
||||
const msgs = []
|
||||
for (const name in task) {
|
||||
msgs.push(`${name} => ${task[name].msg}`)
|
||||
}
|
||||
|
||||
ret.push(
|
||||
{
|
||||
hostname: host,
|
||||
result: msgs.join('\n')
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
@@ -11,6 +11,7 @@ import { GenericDetailPage, TabPage } from '@/layout/components'
|
||||
import TaskDetail from './TaskDetail'
|
||||
import TaskHistory from './TaskHistory'
|
||||
import CeleryTaskLog from '../CeleryTaskLog'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GenericDetailPage,
|
||||
@@ -23,9 +24,7 @@ export default {
|
||||
return {
|
||||
TaskDetail: {},
|
||||
config: {
|
||||
getTitle(row) {
|
||||
return row['display_name']
|
||||
},
|
||||
url: '/api/v1/ops/tasks',
|
||||
activeMenu: 'TaskDetail',
|
||||
submenu: [
|
||||
{
|
||||
|
@@ -14,50 +14,48 @@ export default {
|
||||
tableConfig: {
|
||||
url: '/api/v1/ops/tasks/',
|
||||
columns: [
|
||||
'name', 'display_name', 'queue', 'comment', 'count', 'state', 'last_published_time'
|
||||
'name', 'queue', 'count', 'comment', 'state', 'last_published_time'
|
||||
],
|
||||
columnsMeta: {
|
||||
name: {
|
||||
width: '500px',
|
||||
formatterArgs: {
|
||||
can: true
|
||||
}
|
||||
},
|
||||
display_name: {
|
||||
label: 'display_name',
|
||||
formatter: row => {
|
||||
return row.meta.display_name ? row.meta.display_name : '-'
|
||||
}
|
||||
},
|
||||
comment: {
|
||||
label: 'comment',
|
||||
formatter: (row) => {
|
||||
return row.meta.comment
|
||||
}
|
||||
},
|
||||
queue: {
|
||||
label: 'queue',
|
||||
width: '120px',
|
||||
label: this.$t('ops.Queue'),
|
||||
formatter: (row) => {
|
||||
return row.meta.queue
|
||||
}
|
||||
},
|
||||
comment: {
|
||||
width: '300px',
|
||||
label: this.$t('common.Comment'),
|
||||
formatter: row => {
|
||||
return row.meta.comment ? row.meta.comment : '-'
|
||||
}
|
||||
},
|
||||
last_published_time: {
|
||||
label: this.$t('ops.LastPublishedTime'),
|
||||
width: '210px',
|
||||
formatter: (row) => {
|
||||
return row.last_published_time != null ? row.last_published_time : '-'
|
||||
}
|
||||
},
|
||||
count: {
|
||||
label: 'success/total',
|
||||
width: '120px',
|
||||
label: `${this.$t('ops.success')}/${this.$t('ops.total')}`,
|
||||
formatter: (row) => {
|
||||
return <div>
|
||||
<span Class='text-primary'>{row.success_count}</span>/
|
||||
<span>{row.publish_count}</span>
|
||||
<span Class='text-primary'>{row.summary.success}</span>/
|
||||
<span>{row.summary.total}</span>
|
||||
</div>
|
||||
}
|
||||
},
|
||||
state: {
|
||||
width: '60px',
|
||||
label: this.$t('ops.State'),
|
||||
width: '120px',
|
||||
align: 'center',
|
||||
formatter: (row) => {
|
||||
switch (row.state) {
|
||||
|
Reference in New Issue
Block a user