perf: 任务列表优化

This commit is contained in:
Aaron3S
2022-11-16 11:11:40 +08:00
parent b21d1533de
commit cfedd153c8
9 changed files with 37 additions and 268 deletions

View File

@@ -669,6 +669,7 @@
"selectedAssets": "已选择资产:",
"stat": "成功/失败/总",
"success": "成功",
"total": "总共",
"taskDetail": "任务详情",
"taskName": "任务名称",
"taskVersions": "任务各版本",
@@ -692,7 +693,10 @@
"myAdhoc": "我的命令",
"history": "历史记录",
"createAdhoc": "创建命令",
"AdhocDetail": "命令详情"
"AdhocDetail": "命令详情",
"Queue": "队列",
"State": "状态",
"LastPublishedTime": "最后发布时间"
},
"perms": {
"": "",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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: [
{

View File

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