mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-20 18:49:19 +00:00
perf: 任务列表优化
This commit is contained in:
@@ -669,6 +669,7 @@
|
|||||||
"selectedAssets": "已选择资产:",
|
"selectedAssets": "已选择资产:",
|
||||||
"stat": "成功/失败/总",
|
"stat": "成功/失败/总",
|
||||||
"success": "成功",
|
"success": "成功",
|
||||||
|
"total": "总共",
|
||||||
"taskDetail": "任务详情",
|
"taskDetail": "任务详情",
|
||||||
"taskName": "任务名称",
|
"taskName": "任务名称",
|
||||||
"taskVersions": "任务各版本",
|
"taskVersions": "任务各版本",
|
||||||
@@ -692,7 +693,10 @@
|
|||||||
"myAdhoc": "我的命令",
|
"myAdhoc": "我的命令",
|
||||||
"history": "历史记录",
|
"history": "历史记录",
|
||||||
"createAdhoc": "创建命令",
|
"createAdhoc": "创建命令",
|
||||||
"AdhocDetail": "命令详情"
|
"AdhocDetail": "命令详情",
|
||||||
|
"Queue": "队列",
|
||||||
|
"State": "状态",
|
||||||
|
"LastPublishedTime": "最后发布时间"
|
||||||
},
|
},
|
||||||
"perms": {
|
"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'),
|
key: this.$t('common.Name'),
|
||||||
value: this.object.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: {
|
tableConfig: {
|
||||||
url: `/api/v1/ops/task-executions/?task_id=${this.object.id}`,
|
url: `/api/v1/ops/task-executions/?task_id=${this.object.id}`,
|
||||||
columns: [
|
columns: [
|
||||||
'id', 'state', 'is_finished', 'date_published', 'date_start', 'date_finished', 'actions'
|
'date_start', 'date_finished', 'state', 'is_finished', 'actions'
|
||||||
],
|
],
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
state: {
|
state: {
|
||||||
label: this.$t('ops.state'),
|
|
||||||
width: '120px',
|
|
||||||
formatter: (row) => {
|
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: {
|
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 TaskDetail from './TaskDetail'
|
||||||
import TaskHistory from './TaskHistory'
|
import TaskHistory from './TaskHistory'
|
||||||
import CeleryTaskLog from '../CeleryTaskLog'
|
import CeleryTaskLog from '../CeleryTaskLog'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GenericDetailPage,
|
GenericDetailPage,
|
||||||
@@ -23,9 +24,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
TaskDetail: {},
|
TaskDetail: {},
|
||||||
config: {
|
config: {
|
||||||
getTitle(row) {
|
url: '/api/v1/ops/tasks',
|
||||||
return row['display_name']
|
|
||||||
},
|
|
||||||
activeMenu: 'TaskDetail',
|
activeMenu: 'TaskDetail',
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
|
@@ -14,50 +14,48 @@ export default {
|
|||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/ops/tasks/',
|
url: '/api/v1/ops/tasks/',
|
||||||
columns: [
|
columns: [
|
||||||
'name', 'display_name', 'queue', 'comment', 'count', 'state', 'last_published_time'
|
'name', 'queue', 'count', 'comment', 'state', 'last_published_time'
|
||||||
],
|
],
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
name: {
|
name: {
|
||||||
|
width: '500px',
|
||||||
formatterArgs: {
|
formatterArgs: {
|
||||||
can: true
|
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: {
|
queue: {
|
||||||
label: 'queue',
|
width: '120px',
|
||||||
|
label: this.$t('ops.Queue'),
|
||||||
formatter: (row) => {
|
formatter: (row) => {
|
||||||
return row.meta.queue
|
return row.meta.queue
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
comment: {
|
||||||
|
width: '300px',
|
||||||
|
label: this.$t('common.Comment'),
|
||||||
|
formatter: row => {
|
||||||
|
return row.meta.comment ? row.meta.comment : '-'
|
||||||
|
}
|
||||||
|
},
|
||||||
last_published_time: {
|
last_published_time: {
|
||||||
|
label: this.$t('ops.LastPublishedTime'),
|
||||||
width: '210px',
|
width: '210px',
|
||||||
formatter: (row) => {
|
formatter: (row) => {
|
||||||
return row.last_published_time != null ? row.last_published_time : '-'
|
return row.last_published_time != null ? row.last_published_time : '-'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
count: {
|
count: {
|
||||||
label: 'success/total',
|
label: `${this.$t('ops.success')}/${this.$t('ops.total')}`,
|
||||||
width: '120px',
|
|
||||||
formatter: (row) => {
|
formatter: (row) => {
|
||||||
return <div>
|
return <div>
|
||||||
<span Class='text-primary'>{row.success_count}</span>/
|
<span Class='text-primary'>{row.summary.success}</span>/
|
||||||
<span>{row.publish_count}</span>
|
<span>{row.summary.total}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
width: '60px',
|
label: this.$t('ops.State'),
|
||||||
|
width: '120px',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
formatter: (row) => {
|
formatter: (row) => {
|
||||||
switch (row.state) {
|
switch (row.state) {
|
||||||
|
Reference in New Issue
Block a user