Files
EasyFlow/easyflow-ui-admin/app/src/views/system/sysJob/SysJobModal.vue
陈子默 8c334be65d fix: 防止定时任务引用失效工作流
- 保存任务时校验工作流权限与必填参数

- 删除工作流前检查并重新确认定时任务引用
2026-08-03 14:50:28 +08:00

272 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import type { FormInstance } from 'element-plus';
import { computed, onMounted, ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import { ElAlert, ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { api } from '#/api/request';
import CronPicker from '#/components/cron/CronPicker.vue';
import DictSelect from '#/components/dict/DictSelect.vue';
import { $t } from '#/locales';
import WorkflowFormItem from '#/views/ai/workflow/components/WorkflowFormItem.vue';
const emit = defineEmits(['reload']);
// vue
onMounted(() => {});
defineExpose({
openDialog,
});
const saveForm = ref<FormInstance>();
// variables
const dialogVisible = ref(false);
const isAdd = ref(true);
const initEntity = {
deptId: '',
jobName: '',
jobType: '',
jobParams: {
workflowParams: {},
},
cronExpression: '',
allowConcurrent: 0,
misfirePolicy: 3,
options: '',
status: '',
remark: '',
};
const entity = ref<any>(initEntity);
const btnLoading = ref(false);
// 基础验证规则
const baseRules = ref({
jobName: [
{ required: true, message: $t('message.required'), trigger: 'blur' },
],
jobType: [
{ required: true, message: $t('message.required'), trigger: 'blur' },
],
cronExpression: [
{ required: true, message: $t('message.required'), trigger: 'blur' },
],
allowConcurrent: [
{ required: true, message: $t('message.required'), trigger: 'blur' },
],
misfirePolicy: [
{ required: true, message: $t('message.required'), trigger: 'blur' },
],
});
const paramsLoading = ref(false);
const workflowParams = ref<any[]>([]);
const workflowParamsLoadError = ref('');
const rules = ref({ ...baseRules.value });
let workflowParamsRequestId = 0;
const workflowParamsSubmissionBlocked = computed(
() =>
entity.value.jobType === 1 &&
(paramsLoading.value || Boolean(workflowParamsLoadError.value)),
);
// functions
function openDialog(row: any) {
resetWorkflowParamsState();
if (row.id) {
entity.value = { ...row };
// 确保 jobParams 存在
if (!entity.value.jobParams) {
entity.value.jobParams = {};
}
if (entity.value.jobParams.workflowId) {
getWorkflowParams(entity.value.jobParams.workflowId);
}
isAdd.value = false;
} else {
entity.value = { ...initEntity };
}
dialogVisible.value = true;
}
function save() {
if (btnLoading.value || workflowParamsSubmissionBlocked.value) {
return;
}
saveForm.value?.validate((valid) => {
if (!valid || btnLoading.value || workflowParamsSubmissionBlocked.value) {
return;
}
btnLoading.value = true;
api
.post(
isAdd.value ? 'api/v1/sysJob/save' : 'api/v1/sysJob/update',
entity.value,
)
.then((res) => {
btnLoading.value = false;
if (res.errorCode === 0) {
ElMessage.success(res.message);
emit('reload');
closeDialog();
}
})
.catch(() => {
btnLoading.value = false;
});
});
}
function closeDialog() {
saveForm.value?.resetFields();
isAdd.value = true;
entity.value = { ...initEntity };
resetWorkflowParamsState();
dialogVisible.value = false;
}
function jobTypeChange(v: any) {
resetWorkflowParamsState();
entity.value.jobParams = {
workflowParams: {},
};
if (v === 1) {
entity.value.jobParams.workflowParams = {};
}
}
function workflowChange(v: any) {
entity.value.jobParams.workflowParams = {};
getWorkflowParams(v);
}
function resetWorkflowParamsState() {
workflowParamsRequestId += 1;
paramsLoading.value = false;
workflowParams.value = [];
workflowParamsLoadError.value = '';
}
async function getWorkflowParams(v: any) {
const requestId = ++workflowParamsRequestId;
paramsLoading.value = true;
workflowParams.value = [];
workflowParamsLoadError.value = '';
try {
const res = await api.get(`/api/v1/workflow/getRunningParameters?id=${v}`);
if (requestId !== workflowParamsRequestId) {
return;
}
workflowParams.value = Array.isArray(res.data?.parameters)
? res.data.parameters
: [];
} catch {
if (requestId === workflowParamsRequestId) {
workflowParamsLoadError.value = '所选工作流已不可用,请重新选择';
}
} finally {
if (requestId === workflowParamsRequestId) {
paramsLoading.value = false;
}
}
}
const str = '"param"';
</script>
<template>
<EasyFlowFormModal
v-model:open="dialogVisible"
:closable="!btnLoading"
:title="isAdd ? $t('button.add') : $t('button.edit')"
:before-close="closeDialog"
:confirm-disabled="workflowParamsSubmissionBlocked"
:confirm-loading="btnLoading || paramsLoading"
:confirm-text="$t('button.save')"
:submitting="btnLoading"
@confirm="save"
>
<ElForm
v-loading="paramsLoading"
ref="saveForm"
:model="entity"
status-icon
:rules="rules"
label-position="top"
class="easyflow-modal-form easyflow-modal-form--compact"
>
<ElFormItem prop="jobName" :label="$t('sysJob.jobName')">
<ElInput v-model.trim="entity.jobName" />
</ElFormItem>
<ElFormItem prop="cronExpression" :label="$t('sysJob.cronExpression')">
<ElInput v-model.trim="entity.cronExpression" />
<CronPicker v-model="entity.cronExpression" />
</ElFormItem>
<ElFormItem prop="jobType" :label="$t('sysJob.jobType')">
<DictSelect
v-model="entity.jobType"
dict-code="jobType"
@change="jobTypeChange"
/>
</ElFormItem>
<ElFormItem
v-if="entity.jobType === 1"
:label="$t('sysJob.workflow')"
prop="jobParams.workflowId"
:rules="[
{ required: true, message: $t('message.required'), trigger: 'blur' },
]"
>
<DictSelect
v-model="entity.jobParams.workflowId"
dict-code="aiWorkFlow"
@change="workflowChange"
/>
</ElFormItem>
<ElAlert
v-if="workflowParamsLoadError"
:title="workflowParamsLoadError"
type="error"
:closable="false"
show-icon
/>
<WorkflowFormItem
v-model:run-params="entity.jobParams.workflowParams"
:parameters="workflowParams"
prop-prefix="jobParams.workflowParams."
/>
<ElFormItem
v-if="entity.jobType === 2"
:label="$t('sysJob.beanMethod')"
prop="jobParams.beanMethod"
:rules="[
{ required: true, message: $t('message.required'), trigger: 'blur' },
]"
>
<ElInput v-model="entity.jobParams.beanMethod" />
<ElAlert
style="margin-top: 5px"
:title="`${$t('sysJob.example')}sysJobServiceImpl.testParam(${str},false,299)`"
/>
</ElFormItem>
<ElFormItem
v-if="entity.jobType === 3"
:label="$t('sysJob.javaMethod')"
prop="jobParams.javaMethod"
:rules="[
{ required: true, message: $t('message.required'), trigger: 'blur' },
]"
>
<ElInput v-model="entity.jobParams.javaMethod" />
<ElAlert
style="margin-top: 5px"
:title="`${$t('sysJob.example')}tech.easyflow.job.util.JobUtil.execTest(${str},1,0.52D,100L)`"
/>
</ElFormItem>
<ElFormItem prop="allowConcurrent" :label="$t('sysJob.allowConcurrent')">
<DictSelect v-model="entity.allowConcurrent" dict-code="yesOrNo" />
</ElFormItem>
<ElFormItem prop="misfirePolicy" :label="$t('sysJob.misfirePolicy')">
<DictSelect v-model="entity.misfirePolicy" dict-code="misfirePolicy" />
</ElFormItem>
<ElFormItem prop="remark" :label="$t('sysJob.remark')">
<ElInput v-model.trim="entity.remark" />
</ElFormItem>
</ElForm>
</EasyFlowFormModal>
</template>
<style scoped></style>