首页工作流表单卡片化闭环:执行进度、输入禁用与取消入口
- socket 节点事件推进表单卡片执行进度,失败详情展示详细原因 - 工作流执行时禁用输入框,取消入口移到卡片 footer,卡片定格可重试 - 工作流 ModelRequestParams 按详情原样透传后端 - 会话内产出文件卡片展示(预览/下载/删除),移除顶部结果卡片区 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -141,11 +141,23 @@
|
||||
<!-- 底部操作区:editing 提交 / running 执行中 / done·failed 定格状态 -->
|
||||
<div class="workflow-form-footer">
|
||||
<div v-if="isFailed" class="form-error-text">{{ formError }}</div>
|
||||
<el-button v-if="submitting" type="primary" loading disabled>执行中...</el-button>
|
||||
<!-- 执行中:节点文本进度推进(后端 node_start/node_complete 事件),无进度时兜底「执行中...」 -->
|
||||
<!-- 取消执行:工作流执行中的终止入口(InputBar 停止按钮对工作流禁用,改由卡片 footer 提供) -->
|
||||
<div v-if="submitting" class="executing-progress">
|
||||
<span class="exec-spinner" />
|
||||
<span class="exec-text">{{ progressText }}</span>
|
||||
<el-button size="small" class="exec-cancel-btn" @click="emit('cancel')">取消执行</el-button>
|
||||
</div>
|
||||
<el-button v-else-if="!readonly" type="primary" :disabled="submitting" @click="handleSubmit">提交执行</el-button>
|
||||
<el-tag v-else :type="isFailed ? 'danger' : 'success'" size="small" effect="light">
|
||||
{{ isFailed ? '执行失败' : '执行完成' }}
|
||||
</el-tag>
|
||||
<template v-else>
|
||||
<el-tag :type="isFailed ? 'danger' : 'success'" size="small" effect="light">
|
||||
{{ isFailed ? '执行失败' : '执行完成' }}
|
||||
</el-tag>
|
||||
<!-- 失败卡片可「重新编辑并执行」:保留已填值切回可编辑,改完重新提交 -->
|
||||
<el-button v-if="isFailed" size="small" @click="emit('re-edit')">
|
||||
<el-icon><RefreshRight /></el-icon>重新编辑并执行
|
||||
</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -153,6 +165,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { RefreshRight } from '@element-plus/icons-vue';
|
||||
import PatchTemplateEditor from '/@/components/patchTemplate/PatchTemplateEditor.vue';
|
||||
import { uploadFile } from '/@/api/common/upload';
|
||||
import { collectHomeFormFields } from '../utils/flowDsl';
|
||||
@@ -166,16 +179,23 @@ interface Props {
|
||||
submitting?: boolean;
|
||||
// 执行失败信息(有值即 failed 态)
|
||||
formError?: string;
|
||||
// 执行进度(后端 node_start/node_complete 事件推进):当前节点序 / 总节点数 / 节点名
|
||||
progress?: { current: number; total: number; nodeName: string };
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'submit', payload: { formValues: Record<string, any>; formFileNames: Record<string, string | string[]>; templates: any[] }): void;
|
||||
// 失败卡片「重新编辑并执行」:由父组件把 formStatus 切回 editing,保留已填值
|
||||
(e: 're-edit'): void;
|
||||
// 执行中取消:工作流取消入口(InputBar 停止按钮对工作流禁用)
|
||||
(e: 'cancel'): void;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
readonly: false,
|
||||
submitting: false,
|
||||
formError: '',
|
||||
progress: () => ({ current: 0, total: 0, nodeName: '' }),
|
||||
});
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
@@ -190,6 +210,16 @@ const templates = ref<any[]>([]);
|
||||
const isFailed = computed(() => !!props.formError);
|
||||
const isDisabled = computed(() => props.readonly || props.submitting);
|
||||
|
||||
// 执行进度文本:有节点进度(current/total>0)显示「正在执行 N/M:节点名」,否则兜底「执行中...」
|
||||
const progressText = computed(() => {
|
||||
const p = props.progress;
|
||||
if (p && p.total > 0 && p.current > 0) {
|
||||
const name = p.nodeName ? `:${p.nodeName}` : '';
|
||||
return `正在执行 ${p.current}/${p.total}${name}...`;
|
||||
}
|
||||
return '执行中...';
|
||||
});
|
||||
|
||||
const getFieldKey = (node: any, field: any): string => {
|
||||
const id = node.id || node.nodeCode;
|
||||
return `${id}|${field.path || field.field || field.label}`;
|
||||
@@ -551,10 +581,40 @@ const handleSubmit = () => {
|
||||
font-size: 12px;
|
||||
color: #ef4444;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap; /* 失败详情可能含换行(error 字段多行原因),允许换行展示 */
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
/* 执行进度:spinner + 文本,节点事件推进 */
|
||||
.executing-progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
.exec-spinner {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
flex-shrink: 0;
|
||||
border: 2px solid #bfdbfe;
|
||||
border-top-color: #2563eb;
|
||||
border-radius: 50%;
|
||||
animation: exec-spin 0.8s linear infinite;
|
||||
}
|
||||
.exec-text {
|
||||
font-size: 13px;
|
||||
color: #1e293b;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.exec-cancel-btn {
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
@keyframes exec-spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.w100 { width: 100%; }
|
||||
|
||||
Reference in New Issue
Block a user