gtsoft-snail-job-server/frontend/src/views/job/form/JobForm.vue

545 lines
18 KiB
Vue
Raw Normal View History

<template>
<div>
<page-header-wrapper content="定时任务配置" @back="() => $router.go(-1)" style="margin: -24px -1px 0">
<div></div>
</page-header-wrapper>
<a-card :body-style="{padding: '24px 32px'}" :bordered="false" :loading="loading">
<a-form @submit="handleSubmit" :form="form" class="form-row" layout="vertical" style="width: 40%;margin: auto;">
<a-row class="form-row" :gutter="16">
<a-col :lg="24" :md="24" :sm="24">
<a-form-item>
<a-input
hidden
v-decorator="['id']" />
</a-form-item>
<a-form-item label="任务名称" >
<a-input
placeholder="请输入任务名称"
:maxLength="64"
v-decorator="[
'jobName',
{rules: [{ required: true, message: '请输入任务名称', whitespace: true},{required: true, max: 64, message: '最多支持64个字符'}]}
]" />
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="18" :md="18" :sm="24">
<a-form-item label="组">
<a-select
placeholder="请选择组"
v-decorator="['groupName', { rules: [{ required: true, message: '请选择组' }] }]"
>
<a-select-option v-for="item in groupNameList" :value="item" :key="item">{{ item }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :sm="24">
<a-form-item label="状态">
<a-select
placeholder="请选择状态"
v-decorator="[
'jobStatus',
{
initialValue: '1',
rules: [{ required: true, message: '请选择状态'}]
}
]" >
<a-select-option :value="index" v-for="(item, index) in jobStatusEnum" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="12" :md="12" :sm="24">
<a-form-item label="路由策略">
<a-select
placeholder="请选择路由策略"
v-decorator="[
'routeKey',
{
initialValue: '4',
rules: [{ required: true, message: '请选择路由策略'}]
}
]" >
<a-select-option :value="index" v-for="(item, index) in routeKey" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :sm="24">
<a-form-item label="阻塞策略">
<a-select
placeholder="请选择阻塞策略"
v-decorator="[
'blockStrategy',
{
initialValue: '1',
rules: [{ required: true, message: '请选择阻塞策略'}]
}
]" >
<a-select-option :value="index" v-for="(item, index) in blockStrategy" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="8" :md="12" :sm="12">
<a-form-item label="触发类型">
<a-select
placeholder="请选择触发类型"
@change="handleChange"
v-decorator="[
'triggerType',
{
initialValue: '2',
rules: [{ required: true, message: '请选择触发类型'}]
}
]" >
<a-select-option :value="index" v-for="(item, index) in triggerType" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="16" :md="12" :sm="12">
<a-form-item label="间隔时长">
<a-input-number
v-if="triggerTypeValue === '2'"
style="width: -webkit-fill-available"
placeholder="请输入间隔时长(秒)"
:min="1"
v-decorator="[
'triggerInterval',
{initialValue: '60',
rules: [ { required: true, message: '请输入间隔时长'}]}
]" />
<a-input
v-if="triggerTypeValue === '1'"
@click="handlerCron"
placeholder="请输入间隔时长"
v-decorator="[
'triggerInterval',
{rules: [{ required: true, message: '请输入间隔时长', whitespace: true}]}
]" />
<a-input
v-if="triggerTypeValue === '3'"
disabled
placeholder=""
v-decorator="[
'triggerInterval'
]" />
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="8" :md="6" :sm="12">
<a-form-item label="执行器类型">
<a-select
placeholder="请选择执行器类型"
v-decorator="[
'executorType',
{
initialValue: '1',
rules: [{ required: true, message: '请选择执行器类型'}]
}
]" >
<a-select-option :value="index" v-for="(item, index) in executorType" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="16" :md="24" :sm="24">
<a-form-item label="执行器名称">
<a-input
placeholder="请输入执行器名称"
type="textarea"
:rows="1"
v-decorator="[
'executorInfo',
{rules: [{ required: true, message: '请输入执行器名称', whitespace: true}]}
]" />
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="8" :md="12" :sm="24">
<a-form-item label="任务类型">
<a-select
placeholder="请选择任务类型"
@change="handleTaskTypeChange"
v-decorator="[
'taskType',
{
initialValue: taskTypeValue,
rules: [{ required: true, message: '请选择任务类型'}]
}
]" >
<a-select-option :value="index" v-for="(item, index) in taskType" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="16" :md="24" :sm="24">
<a-form-item label="方法参数">
<a-input
placeholder="请输入方法参数"
type="textarea"
:rows="1"
@click="handleBlur"
v-decorator="[
'argsStr',
{rules: [{ required: this.taskTypeValue === '3', message: '请输入方法参数', whitespace: true}]}
]" />
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="6" :md="12" :sm="24">
<a-form-item label="超时时间(秒)">
<a-input-number
id="inputNumber"
:min="1"
:max="36000"
v-decorator="[
'executorTimeout',
{
initialValue: '60',
rules: [{ required: true, message: '请输入超时时间'}]
}
]" />
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :sm="24">
<a-form-item label="最大重试次数">
<a-input-number
:min="0"
v-decorator="[
'maxRetryTimes',
{
initialValue: '3',
rules: [{ required: true, message: '请输入最大重试次数'}]
}
]" />
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :sm="24">
<a-form-item label="重试间隔(秒)">
<a-input-number
:min="1"
v-decorator="[
'retryInterval',
{
initialValue: '1',
rules: [{ required: true, message: '请输入重试间隔'
}]
}
]" />
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :sm="24">
<a-form-item label="并行数">
<a-input-number
:min="1"
v-decorator="[
'parallelNum',
{
initialValue: '1',
rules: [{ required: true, message: '请输入并行数'}]
}
]" />
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="16">
</a-row>
<a-row class="form-row" :gutter="16">
<a-col :lg="24" :md="24" :sm="24">
<a-form-item label="描述">
<a-input
placeholder="请输入描述"
type="textarea"
v-decorator="[
'description',
{rules: [{required: false, max: 256, message: '最多支持256个字符'}]}
]" />
</a-form-item>
</a-col>
</a-row>
<a-form-item
:wrapperCol="{ span: 24 }"
style="text-align: center"
>
<a-button htmlType="submit" type="primary">提交</a-button>
<a-button style="margin-left: 8px" @click="reset">重置</a-button>
</a-form-item>
</a-form>
</a-card>
<a-modal :visible="visible" title="分片参数" @ok="submitForm()" @cancel="handlerCancel" width="500px">
<a-form-model ref="dynamicValidateForm" :model="dynamicValidateForm" style="margin-left: 15%" layout="vertical" >
<a-form-model-item
v-for="(domain, index) in dynamicValidateForm.domains"
:key="domain.key"
:label="'分片' + (index)"
:prop="'domains.' + index + '.value'"
:rules="{
required: true,
message: '分区参数不能为空',
trigger: 'blur',
}"
>
<a-input
v-model="domain.value"
placeholder="请输入分区的参数"
style="width: 80%; margin-right: 8px"
/>
<a-icon
v-if="dynamicValidateForm.domains.length > 1"
class="dynamic-delete-button"
type="minus-circle-o"
:disabled="dynamicValidateForm.domains.length === 1"
@click="removeDomain(domain)"
/>
</a-form-model-item>
<a-form-model-item v-bind="formItemLayoutWithOutLabel">
<a-button type="dashed" style="width: 60%" @click="add">
<a-icon type="plus" /> 添加分片
</a-button>
</a-form-model-item>
<a-form-model-item
:wrapper-col="{
xs: { span: 24, offset: 0 },
sm: { span: 16, offset: 8 },
lg: { span: 7 }
}">
</a-form-model-item>
</a-form-model>
</a-modal>
<cron-modal ref="cronModalRef" @getCron="getCron"/>
</div>
</template>
<script>
import { getAllGroupNameList } from '@/api/manage'
import { getJobDetail, saveJob, updateJob } from '@/api/jobApi'
import pick from 'lodash.pick'
import CronModal from '@/views/job/form/CronModal'
import AFormModel from 'ant-design-vue/es/form-model/Form'
import AFormModelItem from 'ant-design-vue/es/form-model/FormItem'
const enums = require('@/utils/jobEnum')
export default {
name: 'JobFrom',
components: {
CronModal,
AFormModel,
AFormModelItem
},
props: {},
data () {
return {
form: this.$form.createForm(this),
formItemLayout: {
labelCol: {
xs: { span: 24 },
sm: { span: 4 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 }
}
},
formItemLayoutWithOutLabel: {
wrapperCol: {
xs: { span: 24, offset: 0 },
sm: { span: 20, offset: 4 }
}
},
formType: 'create',
groupNameList: [],
jobStatusEnum: enums.jobStatusEnum,
taskType: enums.taskType,
triggerType: enums.triggerType,
blockStrategy: enums.blockStrategy,
executorType: enums.executorType,
routeKey: enums.routeKey,
loading: false,
visible: false,
count: 0,
triggerTypeValue: '2',
taskTypeValue: '1',
argsStrValue: [],
dynamicValidateForm: {
domains: []
}
}
},
beforeCreate () {
// this.dynamicForm = this.$form.createForm(this, { name: 'dynamic_form_item' })
// this.dynamicForm.getFieldDecorator('keys', { initialValue: [], preserve: true })
},
mounted () {
getAllGroupNameList().then((res) => {
this.groupNameList = res.data
})
this.$nextTick(() => {
const id = this.$route.query.id
if (id) {
this.loading = true
getJobDetail(id).then(res => {
this.loadEditInfo(res.data)
this.loading = false
})
}
})
},
methods: {
handleChange (value) {
this.triggerTypeValue = value
this.form.setFieldsValue({
triggerInterval: null
})
},
handleTaskTypeChange (value) {
this.taskTypeValue = value
},
handlerCron () {
const triggerType = this.form.getFieldValue('triggerType')
if (triggerType === '1') {
let triggerInterval = this.form.getFieldValue('triggerInterval')
if (triggerInterval === null || triggerInterval === '') {
triggerInterval = '* * * * * ?'
}
this.$refs.cronModalRef.isShow(triggerInterval)
}
},
removeDomain (item) {
const index = this.dynamicValidateForm.domains.indexOf(item)
if (index !== -1) {
this.dynamicValidateForm.domains.splice(index, 1)
}
},
add () {
this.dynamicValidateForm.domains.push({
value: '',
key: Date.now()
})
},
handleBlur () {
const taskType = this.form.getFieldValue('taskType')
if (taskType === '3') {
this.visible = !this.visible
}
},
getCron (cron) {
this.form.setFieldsValue({
triggerInterval: cron
})
},
submitForm () {
const { form } = this
this.$refs['dynamicValidateForm'].validate(valid => {
if (valid) {
this.argsStrValue = this.dynamicValidateForm.domains.map((item, index) => item.value)
form.setFieldsValue({
argsStr: this.dynamicValidateForm.domains.map((item, index) => `分区:${index}=>${item.value}`).join('; ')
})
this.visible = !this.visible
} else {
console.log('error submit!!')
return false
}
})
},
handleOk (e) {
const { form } = this
e.preventDefault()
this.dynamicForm.validateFields((err, values) => {
if (!err) {
this.argsStrValue = values['sharding']
console.log(this.argsStrValue)
form.setFieldsValue({
argsStr: this.argsStrValue.filter(item => item).map((item, index) => `分区:${index}=>${item}`).join('; ')
})
this.visible = false
}
})
},
handlerCancel () {
this.visible = false
},
handleSubmit (e) {
e.preventDefault()
this.form.validateFields((err, values) => {
if (!err) {
if (this.taskTypeValue === '3') {
values['argsStr'] = JSON.stringify(this.argsStrValue)
}
if (this.triggerTypeValue === '3') {
values['triggerInterval'] = '0'
}
if (this.formType === 'create') {
saveJob(values).then(res => {
this.$message.success('任务新增完成')
this.form.resetFields()
this.$router.go(-1)
})
} else {
updateJob(values).then(res => {
this.$message.success('任务更新完成')
this.form.resetFields()
this.$router.go(-1)
})
}
}
})
},
loadEditInfo (data) {
this.formType = 'edit'
const { form } = this
// ajax
new Promise((resolve) => {
setTimeout(resolve, 100)
}).then(() => {
const formData = pick(data, [
'id', 'jobName', 'groupName', 'jobStatus', 'executorInfo', 'argsStr', 'executorTimeout', 'description',
'maxRetryTimes', 'parallelNum', 'retryInterval', 'triggerType', 'blockStrategy', 'executorType', 'taskType', 'triggerInterval'])
formData.jobStatus = formData.jobStatus.toString()
formData.taskType = formData.taskType.toString()
formData.executorType = formData.executorType.toString()
formData.blockStrategy = formData.blockStrategy.toString()
formData.triggerType = formData.triggerType.toString()
this.triggerTypeValue = formData.triggerType
this.taskTypeValue = formData.taskType
if (this.triggerTypeValue === '3') {
formData.triggerInterval = null
}
if (this.taskTypeValue === '3') {
this.argsStrValue = JSON.parse(formData.argsStr)
formData.argsStr = this.argsStrValue.map((item, index) => `分区:${index}=>${item}`).join(';')
this.argsStrValue.forEach((item, index) => {
this.dynamicValidateForm.domains.push({
value: item,
key: Date.now() + index
})
})
}
form.setFieldsValue(formData)
})
},
reset () {
this.form.resetFields()
this.dynamicForm.resetFields()
}
}
}
</script>