feat: 支持作业定时执行

This commit is contained in:
Aaron3S
2022-11-18 19:01:32 +08:00
parent 4b84a77a5a
commit fc9b44db21
5 changed files with 105 additions and 21 deletions

View File

@@ -703,7 +703,17 @@
"Plan": "计划", "Plan": "计划",
"AssetAmount": "资产数量", "AssetAmount": "资产数量",
"SelectAdhoc": "选择命令", "SelectAdhoc": "选择命令",
"SaveAdhoc": "保存命令" "SaveAdhoc": "保存命令",
"RunJob": "运行作业",
"Parameter": "参数",
"Summary(success/total)": "概况( 成功/总数 )",
"DateLastRun": "上次运行日期",
"AverageTimeCost": "平均花费时间",
"ThisPeriodic": "这是一个周期作业",
"JobType": "作业类型",
"Comment": "备注",
"History": "执行历史",
"UseParameterDefine": "定义参数"
}, },
"perms": { "perms": {
"": "", "": "",
@@ -886,6 +896,7 @@
"JobList": "作业列表", "JobList": "作业列表",
"JobCreate": "创建作业", "JobCreate": "创建作业",
"JobUpdate": "更新作业", "JobUpdate": "更新作业",
"JobDetail": "作业详情",
"LabelCreate": "创建标签", "LabelCreate": "创建标签",
"LabelList": "标签管理", "LabelList": "标签管理",
"LabelUpdate": "更新标签", "LabelUpdate": "更新标签",

View File

@@ -31,6 +31,30 @@ export default {
{ {
key: this.$t('common.Name'), key: this.$t('common.Name'),
value: this.object.name value: this.object.name
},
{
key: this.$t('ops.JobType'),
value: this.object.type
},
{
key: this.$t('ops.Comment'),
value: this.object.comment
},
{
key: this.$t('ops.AverageTimeCost'),
value: this.object.average_time_cost.toFixed(2) + 's'
},
{
key: this.$t('ops.DateLastRun'),
value: this.object.date_last_run
},
{
key: this.$t('common.DateUpdated'),
value: this.object.date_updated
},
{
key: this.$t('common.DateCreated'),
value: this.object.date_created
} }
] ]
} }

View File

@@ -1,7 +1,7 @@
<template> <template>
<Dialog <Dialog
v-if="iVisible" v-if="iVisible && ready"
:title="$tc('ops.SaveAdhoc')" :title="$tc('ops.RunJob')"
:visible.sync="iVisible" :visible.sync="iVisible"
width="50%" width="50%"
top="1vh" top="1vh"
@@ -10,7 +10,7 @@
> >
<el-form ref="form" :model="form" label-width="140px"> <el-form ref="form" :model="form" label-width="140px">
<el-form-item v-for="(item,key,index) in vars" :key="index" :label="item.label"> <el-form-item v-for="(item,key,index) in vars" :key="index" :label="item.label">
<template v-if="item.type === 'select'"> <div v-if="item.type === 'select'">
<el-select v-model="form[key]"> <el-select v-model="form[key]">
<el-option <el-option
v-for="option in item.options" v-for="option in item.options"
@@ -19,10 +19,10 @@
:value="option.value" :value="option.value"
/> />
</el-select> </el-select>
</template> </div>
<template v-else> <div v-else>
<el-input v-model="form[key]" /> <el-input v-model="form[key]" />
</template> </div>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="onSubmit">执行</el-button> <el-button type="primary" @click="onSubmit">执行</el-button>
@@ -50,6 +50,7 @@ export default {
}, },
data() { data() {
return { return {
ready: false,
vars: {}, vars: {},
form: {} form: {}
} }
@@ -67,8 +68,9 @@ export default {
mounted() { mounted() {
this.vars = JSON.parse(this.item.parameters_define) this.vars = JSON.parse(this.item.parameters_define)
for (const key of Object.keys(this.vars)) { for (const key of Object.keys(this.vars)) {
this.form[key] = this.vars[key].default || '' this.$set(this.form, key, this.vars[key].default || '')
} }
this.ready = true
}, },
methods: { methods: {
onSubmit() { onSubmit() {

View File

@@ -9,6 +9,8 @@ import { GenericCreateUpdatePage } from '@/layout/components'
import AssetSelect from '@/components/AssetSelect' import AssetSelect from '@/components/AssetSelect'
import { JsonEditor } from '@/components/FormFields' import { JsonEditor } from '@/components/FormFields'
import JobCodeEditor from '@/views/ops/Job/JobCodeEditor' import JobCodeEditor from '@/views/ops/Job/JobCodeEditor'
import { CronTab } from '@/components'
import i18n from '@/i18n/i18n'
export default { export default {
components: { components: {
@@ -25,8 +27,8 @@ export default {
[this.$t('common.Basic'), ['name', 'type', 'instant', 'comment']], [this.$t('common.Basic'), ['name', 'type', 'instant', 'comment']],
[this.$t('common.Task'), ['module', 'args', 'playbook', 'chdir', 'timeout']], [this.$t('common.Task'), ['module', 'args', 'playbook', 'chdir', 'timeout']],
[this.$t('ops.Asset'), ['assets', 'runas', 'runas_policy']], [this.$t('ops.Asset'), ['assets', 'runas', 'runas_policy']],
[this.$t('ops.Variable'), ['parameters_define']], [this.$t('ops.Plan'), ['runAfterSave', 'is_periodic', 'crontab']],
[this.$t('ops.Plan'), ['runAfterSave', 'periodic', 'crontab']] [this.$t('ops.Parameter'), ['use_parameter_define', 'parameters_define']]
], ],
initial: { initial: {
type: 'adhoc', type: 'adhoc',
@@ -37,7 +39,7 @@ export default {
instant: false, instant: false,
parameters_define: '{}', parameters_define: '{}',
timeout: 60, timeout: 60,
periodic: false, is_periodic: false,
crontab: '0 0 * * *' crontab: '0 0 * * *'
}, },
fieldsMeta: { fieldsMeta: {
@@ -91,7 +93,10 @@ export default {
}, },
parameters_define: { parameters_define: {
label: this.$t('ops.Variable'), label: this.$t('ops.Variable'),
component: JsonEditor component: JsonEditor,
hidden: (formValue) => {
return !formValue.use_parameter_define
}
}, },
chdir: { chdir: {
hidden: (formValue) => { hidden: (formValue) => {
@@ -105,15 +110,21 @@ export default {
return formValue.instant return formValue.instant
} }
}, },
periodic: { use_parameter_define: {
label: '定时执行', label: this.$t('ops.UseParameterDefine'),
type: 'checkbox' type: 'switch'
},
is_periodic: {
type: 'switch'
}, },
crontab: { crontab: {
label: '表达式', type: 'cronTab',
component: CronTab,
label: i18n.t('xpack.RegularlyPerform'),
hidden: (formValue) => { hidden: (formValue) => {
return !formValue.periodic return formValue.is_periodic === false
} },
helpText: i18n.t('xpack.HelpText.CrontabOfCreateUpdatePage')
} }
} }
} }

View File

@@ -7,7 +7,7 @@
<script> <script>
import GenericListPage from '@/layout/components/GenericListPage' import GenericListPage from '@/layout/components/GenericListPage'
import { ActionsFormatter } from '@/components/TableFormatters' import { ActionsFormatter, DateFormatter } from '@/components/TableFormatters'
import { openTaskPage } from '@/utils/jms' import { openTaskPage } from '@/utils/jms'
import JobRunDialog from '@/views/ops/Job/JobRunDialog' import JobRunDialog from '@/views/ops/Job/JobRunDialog'
@@ -24,20 +24,55 @@ export default {
tableConfig: { tableConfig: {
url: '/api/v1/ops/jobs/', url: '/api/v1/ops/jobs/',
columns: [ columns: [
'name', 'type', 'asset_amount', 'comment', 'date_updated', 'date_created', 'actions' 'name', 'type', 'summary', 'average_time_cost', 'asset_amount', 'date_last_run', 'comment', 'date_updated', 'date_created', 'actions'
], ],
columnsShow: {
min: ['name', 'actions'],
default: ['name', 'type', 'asset_amount', 'average_time_cost', 'summary', 'comment', 'date_last_run', 'actions']
},
columnsMeta: { columnsMeta: {
name: { name: {
formatterArgs: { formatterArgs: {
can: true can: true
} }
}, },
type: {
formatter: (row) => {
if (row.is_periodic) {
return <span>{row.type}&nbsp;
<el-tooltip content={this.$t('ops.ThisPeriodic')}>
<i Class='fa fa-circle-o text-primary' />
</el-tooltip>
</span>
}
return <span>{row.type}</span>
}
},
summary: {
label: this.$t('ops.Summary(success/total)'),
width: '140px',
formatter: (row) => {
return row.summary['success'] + '/' + row.summary['total']
}
},
average_time_cost: {
label: this.$t('ops.AverageTimeCost'),
width: '140px',
formatter: (row) => {
return row.average_time_cost.toFixed(2) + 's'
}
},
asset_amount: { asset_amount: {
width: '140px',
label: this.$t('ops.AssetAmount'), label: this.$t('ops.AssetAmount'),
formatter: (row) => { formatter: (row) => {
return row.assets.length return row.assets.length
} }
}, },
date_last_run: {
label: this.$t('ops.DateLastRun'),
formatter: DateFormatter
},
actions: { actions: {
formatter: ActionsFormatter, formatter: ActionsFormatter,
formatterArgs: { formatterArgs: {
@@ -54,7 +89,8 @@ export default {
type: 'running', type: 'running',
can: true, can: true,
callback: ({ row }) => { callback: ({ row }) => {
if (row.parameters_define) { const params = JSON.parse(row.parameters_define)
if (Object.keys(params).length > 0) {
this.item = row this.item = row
this.showJobRunDialog = true this.showJobRunDialog = true
} else { } else {