feat(workflow): 优化工作流节点展示和功能

- 修改工作流节点的样式和布局
- 优化条件节点的表达式显示
- 调整回调节点和任务节点的展示内容
- 新增手动触发和工作流调用的执行原因
- 更新多语言文案
This commit is contained in:
csc 2025-06-30 14:42:45 +08:00
parent 1d740bb143
commit 99eb47971d
13 changed files with 70 additions and 59 deletions

View File

@ -125,6 +125,7 @@ const jobTaskChange = (_: string, option: { label: string; value: number }) => {
value: item.id value: item.id
}; };
}) })
.filter(item => item.value != store.id)
" "
@update:value="jobTaskChange" @update:value="jobTaskChange"
/> />

View File

@ -97,7 +97,7 @@ const toText = (node: Workflow.NodeModelType, currentIndex: number) => {
if (nodeName !== $t('workflow.node.condition.conditionNodes.otherNodeName')) { if (nodeName !== $t('workflow.node.condition.conditionNodes.otherNodeName')) {
const text = `<span class="content_label">${$t('workflow.node.condition.conditionNodes.expressionType')}: </span>${ const text = `<span class="content_label">${$t('workflow.node.condition.conditionNodes.expressionType')}: </span>${
expressionRecord[expressionType!] expressionRecord[expressionType!]
}\n<span class="content_label">${$t('workflow.node.condition.conditionNodes.nodeExpression')}: </span><span style="display: inline-block; vertical-align: bottom; width: 120px; overflow: hidden; text-overflow: ellipsis">${nodeExpression}<span/>`; }`;
return text; return text;
} }
return $t('workflow.node.condition.conditionNodes.otherNodeTip'); return $t('workflow.node.condition.conditionNodes.otherNodeTip');
@ -286,7 +286,7 @@ const getClass = (item: Workflow.ConditionNodeType) => {
.auto-judge { .auto-judge {
white-space: pre; white-space: pre;
min-height: 132px !important; min-height: 79px !important;
} }
.top-tips { .top-tips {

View File

@ -166,16 +166,16 @@ const getClass = (item: Workflow.ConditionNodeType) => {
</div> </div>
<template v-if="item.callback?.webhook"> <template v-if="item.callback?.webhook">
<div class="flex justify-between"> <div class="flex justify-between">
<span class="content_label">Webhook:</span> <!-- <span class="content_label">Webhook:</span>-->
<NEllipsis class="w-116px">{{ item.callback.webhook }}</NEllipsis> <NEllipsis class="w-190px">{{ item.callback.webhook }}</NEllipsis>
</div> </div>
<div> <!-- <div>-->
<span class="content_label"> <!-- <span class="content_label">-->
{{ $t('workflow.node.callback.conditionNodes.contentType') }}: <!-- {{ $t('workflow.node.callback.conditionNodes.contentType') }}:-->
</span> <!-- </span>-->
{{ contentTypeRecord[item.callback.contentType!] }} <!-- {{ contentTypeRecord[item.callback.contentType!] }}-->
</div> <!-- </div>-->
<div>.........</div> <!-- <div>.........</div>-->
</template> </template>
</div> </div>
<NTooltip v-if="store.type === 2 && item.taskBatchStatus"> <NTooltip v-if="store.type === 2 && item.taskBatchStatus">

View File

@ -98,11 +98,11 @@ const show = () => {
{{ nodeData.groupName }} {{ nodeData.groupName }}
</NEllipsis> </NEllipsis>
</div> </div>
<div> <!-- <div>-->
<span class="content_label">阻塞策略:&nbsp;</span> <!-- <span class="content_label">阻塞策略:&nbsp;</span>-->
{{ $t(blockStrategyRecord[nodeData.blockStrategy!]) }} <!-- {{ $t(blockStrategyRecord[nodeData.blockStrategy!]) }}-->
</div> <!-- </div>-->
<div>.........</div> <!-- <div>.........</div>-->
</div> </div>
<div v-else class="content min-h-85px"> <div v-else class="content min-h-85px">
<span class="placeholder">请配置工作流</span> <span class="placeholder">请配置工作流</span>

View File

@ -228,16 +228,16 @@ const isShow = (taskBatchStatus: number) => {
<div v-if="!item.jobTask?.jobId" class="placeholder">请选择任务</div> <div v-if="!item.jobTask?.jobId" class="placeholder">请选择任务</div>
<template v-if="item.jobTask?.jobId"> <template v-if="item.jobTask?.jobId">
<div> <div>
<span class="content_label">任务名称:&nbsp;</span> <!-- <span class="content_label">任务名称:&nbsp;</span>-->
<NEllipsis class="max-w-123px"> <NEllipsis class="max-w-123px">
{{ `${item.jobTask?.jobName}(${item.jobTask?.jobId})` }} {{ `${item.jobTask?.jobName}(${item.jobTask?.jobId})` }}
</NEllipsis> </NEllipsis>
</div> </div>
<div> <!-- <div>-->
<span class="content_label">失败策略:&nbsp;</span> <!-- <span class="content_label">失败策略:&nbsp;</span>-->
{{ $t(failStrategyRecord[item.failStrategy!]) }} <!-- {{ $t(failStrategyRecord[item.failStrategy!]) }}-->
</div> <!-- </div>-->
<div>.........</div> <!-- <div>.........</div>-->
</template> </template>
</div> </div>
<div <div

View File

@ -225,16 +225,16 @@ const isShow = (taskBatchStatus: number) => {
<div v-if="!item.subWorkflow?.id" class="placeholder">请选择工作流</div> <div v-if="!item.subWorkflow?.id" class="placeholder">请选择工作流</div>
<template v-if="item.subWorkflow?.id"> <template v-if="item.subWorkflow?.id">
<div> <div>
<span class="content_label">工作流名称:&nbsp;</span> <!-- <span class="content_label">工作流名称:&nbsp;</span>-->
<NEllipsis class="max-w-123px"> <NEllipsis class="max-w-123px">
{{ `${item.subWorkflow?.name}(${item.subWorkflow?.id})` }} {{ `${item.subWorkflow?.name}(${item.subWorkflow?.id})` }}
</NEllipsis> </NEllipsis>
</div> </div>
<div> <!-- <div>-->
<span class="content_label">失败策略:&nbsp;</span> <!-- <span class="content_label">失败策略:&nbsp;</span>-->
{{ $t(failStrategyRecord[item.failStrategy!]) }} <!-- {{ $t(failStrategyRecord[item.failStrategy!]) }}-->
</div> <!-- </div>-->
<div>.........</div> <!-- <div>.........</div>-->
</template> </template>
</div> </div>
<div <div

View File

@ -270,7 +270,7 @@
width: 220px; width: 220px;
min-height: 72px; min-height: 72px;
background: rgb(255, 255, 255); background: rgb(255, 255, 255);
border-radius: 4px; border-radius: 10px;
padding: 15px 15px; padding: 15px 15px;
cursor: pointer; cursor: pointer;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1);
@ -331,8 +331,8 @@
.auto-judge .content { .auto-judge .content {
line-height: 23px; line-height: 23px;
position: relative; position: relative;
padding-top: 15px; padding-top: 10px;
min-height: 59px; min-height: 33px;
} }
.auto-judge .content .placeholder { .auto-judge .content .placeholder {

View File

@ -270,7 +270,9 @@ export const operationReasonRecord: Record<Api.Common.OperationReason, App.I18n.
11: 'common.jobOperationReason.items.workflowCallbackNodeExecutionError', 11: 'common.jobOperationReason.items.workflowCallbackNodeExecutionError',
12: 'common.jobOperationReason.items.workflowNodeNoRequired', 12: 'common.jobOperationReason.items.workflowNodeNoRequired',
13: 'common.jobOperationReason.items.workflowNodeClosedSkipExecution', 13: 'common.jobOperationReason.items.workflowNodeClosedSkipExecution',
14: 'common.jobOperationReason.items.workflowDecisionFailed' 14: 'common.jobOperationReason.items.workflowDecisionFailed',
15: 'common.jobOperationReason.items.manualTrigger',
16: 'common.jobOperationReason.items.workflowBeCalled',
}; };
export const operationReasonOptions = transformRecordToNumberOption(operationReasonRecord); export const operationReasonOptions = transformRecordToNumberOption(operationReasonRecord);

View File

@ -219,7 +219,9 @@ const local: App.I18n.Schema = {
workflowCallbackNodeExecutionError: 'Callback node execution error', workflowCallbackNodeExecutionError: 'Callback node execution error',
workflowNodeNoRequired: 'No process required', workflowNodeNoRequired: 'No process required',
workflowNodeClosedSkipExecution: 'Node closed, skip execution', workflowNodeClosedSkipExecution: 'Node closed, skip execution',
workflowDecisionFailed: 'Workflow decision failed' workflowDecisionFailed: 'Workflow decision failed',
manualTrigger: 'Manual trigger',
workflowBeCalled: 'WorkflowBeCalled',
} }
}, },
retryOperationReason: { retryOperationReason: {

View File

@ -225,7 +225,9 @@ const local: App.I18n.Schema = {
workflowCallbackNodeExecutionError: '回调节点执行异常', workflowCallbackNodeExecutionError: '回调节点执行异常',
workflowNodeNoRequired: '无需处理', workflowNodeNoRequired: '无需处理',
workflowNodeClosedSkipExecution: '节点关闭跳过执行', workflowNodeClosedSkipExecution: '节点关闭跳过执行',
workflowDecisionFailed: '判定未通过' workflowDecisionFailed: '判定未通过',
manualTrigger: '手动触发',
workflowBeCalled: '工作流中被调用',
} }
}, },
retryOperationReason: { retryOperationReason: {
@ -1015,7 +1017,7 @@ const local: App.I18n.Schema = {
logicalCondition: '判定逻辑', logicalCondition: '判定逻辑',
expressionType: '表达式类型', expressionType: '表达式类型',
nodeExpression: '节点表达式', nodeExpression: '节点表达式',
otherNodeTip: '如存在未满足其他分支条件的情况,进入此分支' otherNodeTip: '其他情况,进入此分支'
}, },
addBranch: '添加条件' addBranch: '添加条件'
}, },
@ -1028,7 +1030,7 @@ const local: App.I18n.Schema = {
} }
}, },
subWorkflow: { subWorkflow: {
nodeName: '工作流', nodeName: '工作流',
conditionNodes: { conditionNodes: {
nodeName: '工作流', nodeName: '工作流',
contentType: '工作流', contentType: '工作流',

View File

@ -114,9 +114,9 @@ declare namespace Api {
/** /**
* 1 2 3JOB已关闭 4 5 6 7 8 9 10 11 12 * 1 2 3JOB已关闭 4 5 6 7 8 9 10 11 12
* 13 14 * 13 14 15 16
*/ */
type OperationReason = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14; type OperationReason = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16;
/** /**
* 1 2 3JOB已关闭 4 5 6 7 8 8 9 10 * 1 2 3JOB已关闭 4 5 6 7 8 8 9 10

View File

@ -512,6 +512,10 @@ declare namespace App {
workflowNodeNoRequired: string; workflowNodeNoRequired: string;
workflowNodeClosedSkipExecution: string; workflowNodeClosedSkipExecution: string;
workflowDecisionFailed: string; workflowDecisionFailed: string;
//手动触发
manualTrigger: string;
//工作流中被调用
workflowBeCalled: string;
}; };
}; };
retryOperationReason: { retryOperationReason: {

View File

@ -97,27 +97,27 @@ const href = (url: string) => {
<component :is="activeModule.component" /> <component :is="activeModule.component" />
</Transition> </Transition>
</div> </div>
<div class="pt-12px text-center"> <!-- <div class="pt-12px text-center">-->
<ButtonIcon <!-- <ButtonIcon-->
tooltip-content="Mail" <!-- tooltip-content="Mail"-->
class="color-#272636 dark:color-#f0f2f5" <!-- class="color-#272636 dark:color-#f0f2f5"-->
icon="simple-icons:maildotru" <!-- icon="simple-icons:maildotru"-->
@click="href('mailto:598092184@qq.com')" <!-- @click="href('mailto:598092184@qq.com')"-->
/> <!-- />-->
<ButtonIcon <!-- <ButtonIcon-->
class="color-#c71d23" <!-- class="color-#c71d23"-->
tooltip-content="Gitee" <!-- tooltip-content="Gitee"-->
icon="simple-icons:gitee" <!-- icon="simple-icons:gitee"-->
@click="href('https://gitee.com/aizuda/snail-job')" <!-- @click="href('https://gitee.com/aizuda/snail-job')"-->
/> <!-- />-->
<ButtonIcon <!-- <ButtonIcon-->
tooltip-content="Github" <!-- tooltip-content="Github"-->
class="color-#010409 dark:color-#e6edf3" <!-- class="color-#010409 dark:color-#e6edf3"-->
icon="simple-icons:github" <!-- icon="simple-icons:github"-->
@click="href('https://github.com/aizuda/snail-job')" <!-- @click="href('https://github.com/aizuda/snail-job')"-->
/> <!-- />-->
</div> <!-- </div>-->
<GlobalFooter /> <!-- <GlobalFooter />-->
</main> </main>
</div> </div>
</NCard> </NCard>