首页工作流:统一执行开关至发送按钮,最后一张已执行卡片参数可编辑
- 工作流表单卡片移除执行/重跑按钮,执行统一由 InputBar 发送按钮触发 - 会话执行过工作流即为工作流对话,下方输入框永久禁止文本输入 - 执行中发送按钮变停止,复用 teardownRound 按 runTypeMap 区分协议 - 最后一张已执行(done/failed)卡片参数保持可编辑,改参后经发送按钮重新执行(含必填校验) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<div class="header-right">
|
||||
<el-tag v-if="submitting" size="small" type="primary">执行中</el-tag>
|
||||
<el-tag v-else-if="isFailed" size="small" type="danger">执行失败</el-tag>
|
||||
<el-tag v-else-if="readonly" size="small" type="success">执行完成</el-tag>
|
||||
<el-tag v-else-if="formStatus === 'done'" size="small" type="success">执行完成</el-tag>
|
||||
<!-- 折叠切换:明确按钮提示用户可展开/收起已填参数(点击标题行同样可切换) -->
|
||||
<button type="button" class="collapse-toggle" @click.stop="toggleCollapse">
|
||||
<el-icon class="collapse-arrow" :class="{ collapsed }"><ArrowDown /></el-icon>
|
||||
@@ -163,29 +163,21 @@
|
||||
<el-empty v-if="!hasFormFields && !currentWorkflowHasPatchLayout" description="该工作流无需填写参数" :image-size="60" />
|
||||
</div>
|
||||
|
||||
<!-- 底部操作区:editing 提交 / running 执行中 / done·failed 定格状态 -->
|
||||
<!-- 底部操作区:editing 提示 / running 执行中 / done·failed 状态标签(执行统一由 InputBar 发送按钮触发) -->
|
||||
<div class="workflow-form-footer">
|
||||
<div v-if="isFailed" class="form-error-text">{{ formError }}</div>
|
||||
<!-- 执行中:节点文本进度推进(后端 node_start/node_complete 事件),无进度时兜底「执行中...」 -->
|
||||
<!-- 取消执行:工作流执行中的终止入口(InputBar 停止按钮对工作流禁用,改由卡片 footer 提供) -->
|
||||
<!-- 执行中:节点文本进度推进(后端 node_start/node_complete 事件),无进度时兜底「执行中...」;
|
||||
停止统一由 InputBar 发送按钮(变停止)触发,卡片内不再提供取消入口 -->
|
||||
<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>
|
||||
<template v-else>
|
||||
<el-tag :type="isFailed ? 'danger' : 'success'" size="small" effect="light">
|
||||
{{ isFailed ? '执行失败' : '执行完成' }}
|
||||
</el-tag>
|
||||
<!-- 失败卡片:可直接「重新执行」(复用当前已填值重跑),或「重新编辑」修改参数后再提交 -->
|
||||
<template v-if="isFailed">
|
||||
<el-button size="small" type="primary" @click="handleRetry">
|
||||
<el-icon><RefreshRight /></el-icon>重新执行
|
||||
</el-button>
|
||||
<el-button size="small" @click="emit('re-edit')">重新编辑</el-button>
|
||||
</template>
|
||||
</template>
|
||||
<!-- 已执行卡片(done/failed,含可编辑的最后一张):显示状态标签,参数是否可编辑由 editable 决定 -->
|
||||
<el-tag v-else-if="formStatus === 'done' || formStatus === 'failed'" :type="isFailed ? 'danger' : 'success'" size="small" effect="light">
|
||||
{{ isFailed ? '执行失败' : '执行完成' }}
|
||||
</el-tag>
|
||||
<!-- 编辑态:无执行按钮,提示通过下方发送按钮执行 -->
|
||||
<span v-else class="form-edit-tip">填写参数后,点击下方发送按钮执行工作流</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -193,7 +185,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { ArrowDown, CircleCheckFilled, CircleCloseFilled, RefreshRight } from '@element-plus/icons-vue';
|
||||
import { ArrowDown, CircleCheckFilled, CircleCloseFilled } from '@element-plus/icons-vue';
|
||||
import PatchTemplateEditor from '/@/components/patchTemplate/PatchTemplateEditor.vue';
|
||||
import { uploadFile } from '/@/api/common/upload';
|
||||
import { collectHomeFormFields } from '../utils/flowDsl';
|
||||
@@ -210,6 +202,10 @@ interface Props {
|
||||
formError?: string;
|
||||
// 执行节点进度(node_start/node_complete 事件驱动的步骤列表,渲染执行过程区)
|
||||
progress?: { nodes: WorkflowNodeStep[] };
|
||||
// InputBar 发送按钮触发执行信号:仅当本卡片为目标时非 null(action 决定 submit/retry)
|
||||
executeSignal?: { action: 'submit' | 'retry'; nonce: number } | null;
|
||||
// 已执行卡片(done/failed)参数可编辑(会话中最后一张执行过的工作流):改参后经发送按钮重新执行
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
@@ -227,6 +223,8 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
submitting: false,
|
||||
formError: '',
|
||||
progress: () => ({ nodes: [] }),
|
||||
executeSignal: null,
|
||||
editable: false,
|
||||
});
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
@@ -237,9 +235,10 @@ const formFileNames = reactive<Record<string, string | string[]>>({});
|
||||
const uploadingFields = reactive<Record<string, boolean>>({});
|
||||
const templates = ref<any[]>([]);
|
||||
|
||||
// 状态派生:失败 = 携带 formError;禁用 = 定格或执行中
|
||||
// 状态派生:失败 = 携带 formError;禁用编辑 = 定格(done/failed)卡片默认只读,
|
||||
// 但最后一张已执行卡片(editable)允许改参;执行中(submitting)一律禁用
|
||||
const isFailed = computed(() => !!props.formError);
|
||||
const isDisabled = computed(() => props.readonly || props.submitting);
|
||||
const isDisabled = computed(() => (props.readonly && !props.editable) || props.submitting);
|
||||
|
||||
// 表单收起/展开:editing(待提交/回显)默认展开;提交(running)自动收起;
|
||||
// done/failed 保持提交时状态(默认收起,用户可手动展开查看已填值)
|
||||
@@ -256,7 +255,8 @@ watch(
|
||||
if (st === 'editing') {
|
||||
collapsed.value = false; // 回显/重新编辑:默认展开
|
||||
} else if (prev === undefined) {
|
||||
collapsed.value = true; // 初始即非编辑态(执行中/完成/失败)→ 收起
|
||||
// 初始即非编辑态(执行中/完成/失败):可编辑的最后一张已执行卡片展开供改参,其余收起
|
||||
collapsed.value = props.editable ? false : true;
|
||||
} else if (st === 'running') {
|
||||
collapsed.value = true; // 提交瞬间自动收起
|
||||
}
|
||||
@@ -541,7 +541,8 @@ watch(
|
||||
);
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (props.readonly || props.submitting) return;
|
||||
// 定格卡片默认只读不可提交;最后一张已执行卡片(editable)允许改参后重新提交
|
||||
if ((props.readonly && !props.editable) || props.submitting) return;
|
||||
if (!validateFormFields()) return;
|
||||
emit('submit', {
|
||||
formValues: JSON.parse(JSON.stringify(formValues)),
|
||||
@@ -550,15 +551,27 @@ const handleSubmit = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 失败后直接重跑:复用当前已填值(必填此前已校验通过),不进入编辑态原样重新提交
|
||||
// 直接重跑:复用当前已填值(必填此前已校验通过),不进入编辑态原样重新提交。
|
||||
// 由 InputBar 发送按钮触发(未重新选择工作流时默认重跑最后一个),成功/失败定格卡片均可重跑
|
||||
const handleRetry = () => {
|
||||
if (!isFailed.value || props.submitting) return;
|
||||
if (!props.readonly || props.submitting) return;
|
||||
emit('retry', {
|
||||
formValues: JSON.parse(JSON.stringify(formValues)),
|
||||
formFileNames: JSON.parse(JSON.stringify(formFileNames)),
|
||||
templates: JSON.parse(JSON.stringify(templates.value || [])),
|
||||
});
|
||||
};
|
||||
|
||||
// InputBar 发送按钮触发执行:父组件把执行信号下发给目标卡片(本卡片为目标时 executeSignal 非 null),
|
||||
// 编辑态调用提交(含必填校验)、定格态调用重跑(复用已填值);卡片参数在组件内部,父组件经信号间接触发
|
||||
watch(
|
||||
() => props.executeSignal,
|
||||
(sig) => {
|
||||
if (!sig) return;
|
||||
if (sig.action === 'submit') handleSubmit();
|
||||
else handleRetry();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -772,6 +785,11 @@ const handleRetry = () => {
|
||||
white-space: pre-wrap; /* 失败详情可能含换行(error 字段多行原因),允许换行展示 */
|
||||
word-break: break-word;
|
||||
}
|
||||
.form-edit-tip {
|
||||
flex: 1;
|
||||
font-size: 12px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
}
|
||||
|
||||
/* 执行进度:spinner + 文本,节点事件推进 */
|
||||
|
||||
Reference in New Issue
Block a user