新增工作流触发类型和事件类型支持

This commit is contained in:
jxxghp
2025-07-22 20:58:55 +08:00
parent 58acde2292
commit 1f7f9ce9db
7 changed files with 215 additions and 13 deletions

View File

@@ -164,6 +164,10 @@ export interface WorkflowShare {
description?: string
// 定时器
timer?: string
// 触发类型timer-定时触发 event-事件触发 manual-手动触发
trigger_type?: string
// 事件类型当trigger_type为event时使用
event_type?: string
// 动作列表
actions?: any[]
// 动作流
@@ -1328,6 +1332,10 @@ export interface Workflow {
description?: string
// 定时器
timer?: string
// 触发类型timer-定时触发 event-事件触发 manual-手动触发
trigger_type?: string
// 事件类型当trigger_type为event时使用
event_type?: string
// 状态
state?: string
// 当前执行动作

View File

@@ -168,7 +168,7 @@ const resolveStatusVariant = (status: string | undefined) => {
if (status === 'S') return { color: 'success', text: t('workflow.task.status.success') }
else if (status === 'R') return { color: 'primary', text: t('workflow.task.status.running') }
else if (status === 'F') return { color: 'error', text: t('workflow.task.status.failed') }
else if (status === 'P') return { color: 'secondary', text: t('workflow.task.status.paused') }
else if (status === 'P') return { color: 'warning', text: t('workflow.task.status.paused') }
else return { color: 'info', text: t('workflow.task.status.waiting') }
}
@@ -272,15 +272,28 @@ const resolveProgress = (item: Workflow) => {
</VCardItem>
<VDivider />
<VCardText class="pa-3">
<div class="d-flex flex-column gap-y-2">
<div class="d-flex flex-column gap-y-3">
<div class="d-flex flex-wrap gap-x-3">
<div class="flex-1">
<div class="mb-1">{{ t('workflow.task.info.timer') }}</div>
<h5 class="text-lg">{{ workflow?.timer }}</h5>
<div class="mb-1">{{ t('workflow.task.info.trigger') }}</div>
<h5>
<span v-if="workflow?.trigger_type === 'timer' || !workflow?.trigger_type">
<VIcon icon="mdi-clock-outline" size="small" class="me-1" />
{{ workflow?.timer }}
</span>
<span v-else-if="workflow?.trigger_type === 'event'">
<VIcon icon="mdi-calendar-check" size="small" class="me-1" />
{{ workflow?.event_type }}
</span>
<span v-else-if="workflow?.trigger_type === 'manual'">
<VIcon icon="mdi-hand-pointing-up" size="small" class="me-1" />
{{ t('workflow.task.info.manualTrigger') }}
</span>
</h5>
</div>
<div class="flex-1">
<div class="mb-1">{{ t('workflow.task.info.status') }}</div>
<h5 class="text-lg" :class="`text-${resolveStatusVariant(workflow?.state).color}`">
<h5 :class="`text-${resolveStatusVariant(workflow?.state).color}`">
{{ resolveStatusVariant(workflow?.state).text }}
</h5>
</div>
@@ -289,14 +302,14 @@ const resolveProgress = (item: Workflow) => {
<div class="flex-1">
<div class="mb-1">{{ t('workflow.task.info.actionCount') }}</div>
<div>
<VAvatar size="28" color="primary" variant="tonal">
<span class="text-sm">{{ workflow?.actions?.length }}</span>
<VAvatar size="24" color="primary" variant="tonal">
<span class="text-xs">{{ workflow?.actions?.length }}</span>
</VAvatar>
</div>
</div>
<div class="flex-1">
<div class="mb-1">{{ t('workflow.task.info.runCount') }}</div>
<h5 class="text-lg">{{ workflow?.run_count }}</h5>
<h5>{{ workflow?.run_count }}</h5>
</div>
</div>
<div class="d-flex flex-wrap gap-x-3">

View File

@@ -190,10 +190,23 @@ async function doDelete() {
<span class="text-body-1"> {{ props.workflow?.share_user }}</span>
</VListItemTitle>
</VListItem>
<VListItem class="ps-0" v-if="props.workflow?.timer">
<VListItem class="ps-0" v-if="props.workflow?.trigger_type || props.workflow?.timer">
<VListItemTitle class="text-center text-md-left">
<span class="font-weight-medium">{{ t('workflow.timer') }}</span>
<span class="text-body-1"> {{ props.workflow?.timer }}</span>
<span class="font-weight-medium">{{ t('workflow.trigger') }}</span>
<span class="text-body-1">
<span v-if="props.workflow?.trigger_type === 'timer' || !props.workflow?.trigger_type">
<VIcon icon="mdi-clock-outline" size="small" class="me-1" />
{{ props.workflow?.timer }}
</span>
<span v-else-if="props.workflow?.trigger_type === 'event'">
<VIcon icon="mdi-calendar-check" size="small" class="me-1" />
{{ props.workflow?.event_type }}
</span>
<span v-else-if="props.workflow?.trigger_type === 'manual'">
<VIcon icon="mdi-hand-pointing-up" size="small" class="me-1" />
{{ t('workflow.manualTrigger') }}
</span>
</span>
</VListItemTitle>
</VListItem>
<VListItem class="ps-0" v-if="parsedWorkflow?.actions">

View File

@@ -33,20 +33,95 @@ const workflowForm = ref<Workflow>(
name: undefined,
timer: undefined,
description: undefined,
trigger_type: 'timer',
event_type: undefined,
state: 'P',
run_count: 0,
},
)
// 监听props变化处理存量数据
watch(
() => props.workflow,
newWorkflow => {
if (newWorkflow) {
// 如果trigger_type为空默认为timer
if (!newWorkflow.trigger_type) {
newWorkflow.trigger_type = 'timer'
}
workflowForm.value = { ...newWorkflow }
}
},
{ immediate: true },
)
// 事件类型列表
const eventTypes = ref<Array<{ title: string; value: string }>>([])
// 触发类型选项
const triggerTypeOptions = computed(() => [
{
title: t('dialog.workflowAddEdit.triggerTypeTimer'),
value: 'timer',
prependIcon: 'mdi-clock-outline',
},
{
title: t('dialog.workflowAddEdit.triggerTypeEvent'),
value: 'event',
prependIcon: 'mdi-calendar-check',
},
{
title: t('dialog.workflowAddEdit.triggerTypeManual'),
value: 'manual',
prependIcon: 'mdi-hand-pointing-up',
},
])
// 加载事件类型列表
async function loadEventTypes() {
try {
eventTypes.value = await api.get('workflow/event_types')
} catch (error) {
console.error('Failed to load event types:', error)
}
}
// 监听触发类型变化
watch(
() => workflowForm.value.trigger_type,
newType => {
if (newType !== 'event') {
workflowForm.value.event_type = undefined
}
},
)
// 提示框
const $toast = useToast()
// 调用API 新增任务
async function addWorkflow() {
if (!workflowForm.value.name || !workflowForm.value.timer) {
if (!workflowForm.value.name) {
$toast.error(t('dialog.workflowAddEdit.nameRequired'))
return
}
if (!workflowForm.value.trigger_type) {
$toast.error(t('dialog.workflowAddEdit.triggerRequired'))
return
}
// 根据触发类型验证必填字段
if (workflowForm.value.trigger_type === 'timer' && !workflowForm.value.timer) {
$toast.error(t('dialog.workflowAddEdit.timerRequired'))
return
}
if (workflowForm.value.trigger_type === 'event' && !workflowForm.value.event_type) {
$toast.error(t('dialog.workflowAddEdit.eventTypeRequired'))
return
}
startNProgress()
try {
const result: { [key: string]: string } = await api.post('workflow/', workflowForm.value)
@@ -64,10 +139,27 @@ async function addWorkflow() {
// 调用API 编辑任务
async function editWorkflow() {
if (!workflowForm.value.name || !workflowForm.value.timer) {
if (!workflowForm.value.name) {
$toast.error(t('dialog.workflowAddEdit.nameRequired'))
return
}
if (!workflowForm.value.trigger_type) {
$toast.error(t('dialog.workflowAddEdit.triggerRequired'))
return
}
// 根据触发类型验证必填字段
if (workflowForm.value.trigger_type === 'timer' && !workflowForm.value.timer) {
$toast.error(t('dialog.workflowAddEdit.timerRequired'))
return
}
if (workflowForm.value.trigger_type === 'event' && !workflowForm.value.event_type) {
$toast.error(t('dialog.workflowAddEdit.eventTypeRequired'))
return
}
startNProgress()
try {
const result: { [key: string]: string } = await api.put(`workflow/${workflowForm.value.id}`, workflowForm.value)
@@ -82,6 +174,11 @@ async function editWorkflow() {
}
doneNProgress()
}
// 组件挂载时加载事件类型
onMounted(() => {
loadEventTypes()
})
</script>
<template>
@@ -109,6 +206,25 @@ async function editWorkflow() {
/>
</VCol>
<VCol cols="12">
<VSelect
v-model="workflowForm.trigger_type"
:label="t('dialog.workflowAddEdit.triggerType')"
:items="triggerTypeOptions"
item-title="title"
item-value="value"
:rules="[requiredValidator]"
prepend-inner-icon="mdi-run"
>
<template #item="{ item, props: itemProps }">
<VListItem v-bind="itemProps">
<template #prepend>
<VIcon :icon="item.raw.prependIcon" />
</template>
</VListItem>
</template>
</VSelect>
</VCol>
<VCol v-if="workflowForm.trigger_type === 'timer'" cols="12">
<VCronField
v-model="workflowForm.timer"
:label="t('dialog.workflowAddEdit.schedule')"
@@ -119,6 +235,19 @@ async function editWorkflow() {
prepend-inner-icon="mdi-clock-outline"
/>
</VCol>
<VCol v-if="workflowForm.trigger_type === 'event'" cols="12">
<VSelect
v-model="workflowForm.event_type"
:label="t('dialog.workflowAddEdit.eventType')"
:items="eventTypes"
item-title="title"
item-value="value"
:rules="[requiredValidator]"
persistent-hint
:hint="t('dialog.workflowAddEdit.eventTypePlaceholder')"
prepend-inner-icon="mdi-calendar-check"
/>
</VCol>
<VCol cols="12">
<VTextarea
v-model="workflowForm.description"

View File

@@ -523,12 +523,14 @@ export default {
waiting: 'Waiting',
},
info: {
trigger: 'Trigger',
timer: 'Timer',
status: 'Status',
actionCount: 'Action Count',
runCount: 'Run Count',
progress: 'Progress',
error: 'Error Message',
manualTrigger: 'Manual',
},
},
scanFile: {
@@ -675,7 +677,9 @@ export default {
searchShares: 'Search Workflow Shares',
noShareData: 'No shared workflows',
sharer: 'Sharer',
trigger: 'Trigger',
timer: 'Timer',
manualTrigger: 'Manual Trigger',
actionCount: 'Action Count',
normalFork: 'Fork Workflow',
cancelShare: 'Cancel Share',
@@ -1867,10 +1871,19 @@ export default {
desc: 'Description',
descPlaceholder: 'Workflow description',
enabled: 'Enabled',
triggerType: 'Trigger Type',
triggerTypeTimer: 'Timer Trigger',
triggerTypeEvent: 'Event Trigger',
triggerTypeManual: 'Manual Trigger',
schedule: 'Schedule',
cronExpr: 'Cron Expression',
cronExprDesc: 'Cron expression for workflow scheduling',
eventType: 'Event Type',
eventTypePlaceholder: 'Please select event type',
nameRequired: 'Please fill in complete information!',
triggerRequired: 'Please select trigger type!',
timerRequired: 'Please fill in timer expression!',
eventTypeRequired: 'Please select event type!',
addSuccess: 'Task created successfully, please edit the workflow!',
addFailed: 'Failed to create task: {message}',
editSuccess: 'Task modified successfully!',

View File

@@ -520,12 +520,14 @@ export default {
waiting: '等待',
},
info: {
trigger: '触发方式',
timer: '定时',
status: '状态',
actionCount: '动作数',
runCount: '已执行次数',
progress: '进度',
error: '错误信息',
manualTrigger: '手动',
},
},
scanFile: {
@@ -672,7 +674,9 @@ export default {
searchShares: '搜索工作流分享',
noShareData: '暂无分享的工作流',
sharer: '分享人',
trigger: '触发方式',
timer: '定时器',
manualTrigger: '手动触发',
actionCount: '动作数量',
normalFork: '复用工作流',
cancelShare: '取消分享',
@@ -1842,10 +1846,19 @@ export default {
desc: '描述',
descPlaceholder: '工作流描述',
enabled: '启用',
triggerType: '触发类型',
triggerTypeTimer: '定时触发',
triggerTypeEvent: '事件触发',
triggerTypeManual: '手动触发',
schedule: '定时执行',
cronExpr: 'Cron表达式',
cronExprDesc: '工作流定时执行的cron表达式',
eventType: '事件类型',
eventTypePlaceholder: '请选择事件类型',
nameRequired: '请填写完整信息!',
triggerRequired: '请选择触发类型!',
timerRequired: '请填写定时表达式!',
eventTypeRequired: '请选择事件类型!',
addSuccess: '创建任务成功,请编辑流程!',
addFailed: '创建任务失败:{message}',
editSuccess: '修改任务成功!',

View File

@@ -518,12 +518,14 @@ export default {
waiting: '等待中',
},
info: {
trigger: '觸發方式',
timer: '定時器',
status: '狀態',
actionCount: '動作數量',
runCount: '執行次數',
progress: '進度',
error: '錯誤訊息',
manualTrigger: '手動',
},
},
scanFile: {
@@ -670,7 +672,9 @@ export default {
searchShares: '搜索工作流分享',
noShareData: '暫無分享的工作流',
sharer: '分享人',
trigger: '觸發方式',
timer: '定時器',
manualTrigger: '手動觸發',
actionCount: '動作數量',
normalFork: '復用工作流',
cancelShare: '取消分享',
@@ -1841,10 +1845,19 @@ export default {
desc: '描述',
descPlaceholder: '工作流描述',
enabled: '啟用',
triggerType: '觸發類型',
triggerTypeTimer: '定時觸發',
triggerTypeEvent: '事件觸發',
triggerTypeManual: '手動觸發',
schedule: '定時執行',
cronExpr: 'Cron表達式',
cronExprDesc: '工作流定時執行的cron表達式',
eventType: '事件類型',
eventTypePlaceholder: '請選擇事件類型',
nameRequired: '請填寫完整資訊!',
triggerRequired: '請選擇觸發類型!',
timerRequired: '請填寫定時表達式!',
eventTypeRequired: '請選擇事件類型!',
addSuccess: '建立任務成功,請編輯流程!',
addFailed: '建立任務失敗:{message}',
editSuccess: '修改任務成功!',