sub_flow 节点引入工作流修复与首页执行工作流重构
- 引入工作流列表字段兼容 flowName,选择弹窗卡片正常展示数据
- 生成次数 maxConcurrency 同步保存到 sub_flow 节点,回显兜底恢复
- valueSource 按后端契约统一 {nodeId, fieldName},表单展示/引用正确保存与回显
- 首页执行工作流 DSL 字段路径改为 .enumValues[i],支持引用上游输出与上传文件名
This commit is contained in:
@@ -32,39 +32,23 @@
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="mf-array-flat">
|
||||
<!-- 联合数组(enumValues 多模板):全部模板平铺,固定条数,不可增删 -->
|
||||
<template v-if="isVariantArray">
|
||||
<div v-for="(item, idx) in getVariantItems()" :key="idx" class="mf-variant">
|
||||
<div class="mf-variant-head">
|
||||
<!-- 数组元素直接遍历模板(enumValues/attrs):值与勾选均落在模板上,
|
||||
保存只留 enumValues 一份即可完整回显,不依赖 value 实例 -->
|
||||
<template v-for="(item, idx) in renderedArrayItems()" :key="idx">
|
||||
<template v-if="isObjectDef(item)">
|
||||
<div v-if="isVariantArray" class="mf-variant-head">
|
||||
<span class="mf-variant-name">{{ variantLabel(idx) }}</span>
|
||||
</div>
|
||||
<template v-if="isObjectDef(item)">
|
||||
<ModelField
|
||||
v-for="(subDef, subKey) in item.attrs"
|
||||
:key="subKey"
|
||||
:field-def="subDef"
|
||||
:path="path ? `${path}.value[${idx}].attrs.${subKey}` : String(subKey)"
|
||||
:upstream-nodes="upstreamNodes"
|
||||
/>
|
||||
</template>
|
||||
<el-input v-else :model-value="item" @input="(v: any) => setArrayPrimitive(idx, v)" size="small" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 同构数组:保持现有平铺逻辑 -->
|
||||
<template v-else>
|
||||
<template v-for="(item, idx) in getArrayValue()" :key="idx">
|
||||
<template v-if="isObjectDef(item)">
|
||||
<div v-if="getArrayValue().length > 1" class="mf-array-flat-index">#{{ idx + 1 }}</div>
|
||||
<ModelField
|
||||
v-for="(subDef, subKey) in item.attrs"
|
||||
:key="subKey"
|
||||
:field-def="subDef"
|
||||
:path="path ? `${path}.value[${idx}].attrs.${subKey}` : String(subKey)"
|
||||
:upstream-nodes="upstreamNodes"
|
||||
/>
|
||||
</template>
|
||||
<el-input v-else :model-value="item" @input="(v: any) => setArrayPrimitive(idx, v)" size="small" />
|
||||
<div v-else-if="renderedArrayItems().length > 1" class="mf-array-flat-index">#{{ idx + 1 }}</div>
|
||||
<ModelField
|
||||
v-for="(subDef, subKey) in item.attrs"
|
||||
:key="subKey"
|
||||
:field-def="subDef"
|
||||
:path="path ? `${path}.enumValues[${idx}].attrs.${subKey}` : String(subKey)"
|
||||
:upstream-nodes="upstreamNodes"
|
||||
/>
|
||||
</template>
|
||||
<el-input v-else :model-value="getTemplatePrimitive(item)" @input="(v: any) => setTemplatePrimitive(item, v)" size="small" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
@@ -177,7 +161,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from 'vue';
|
||||
import { FolderOpened, List, QuestionFilled, Link } from '@element-plus/icons-vue';
|
||||
import { deepClone, normalizeArrayItem } from './modelParamUtils';
|
||||
|
||||
defineOptions({ name: 'ModelField' });
|
||||
|
||||
@@ -312,22 +295,26 @@ const arrayTemplates = computed<any[]>(() => {
|
||||
return [];
|
||||
});
|
||||
|
||||
const getArrayValue = (): any[] => {
|
||||
if (!def.value) return [];
|
||||
if (!Array.isArray(def.value.value)) {
|
||||
def.value.value = [];
|
||||
}
|
||||
// value 为空时(后端仅定义结构未给内容)用模板补一条空结构,保证字段可展示、可填写
|
||||
if (def.value.value.length === 0 && arrayTemplates.value.length > 0) {
|
||||
def.value.value.push(normalizeArrayItem(deepClone(arrayTemplates.value[0])));
|
||||
}
|
||||
return def.value.value;
|
||||
};
|
||||
|
||||
const isObjectDef = (item: any) => !!item && typeof item === 'object' && item.type === 'object' && item.attrs && typeof item.attrs === 'object';
|
||||
|
||||
const setArrayPrimitive = (idx: number, val: any) => {
|
||||
getArrayValue()[idx] = val ?? '';
|
||||
// 数组渲染统一以模板(enumValues/attrs)为数据源:值与勾选均落在模板上,
|
||||
// 不受 props 同步重建 localParams(深拷贝)影响,保存只留 enumValues 一份即可完整回显
|
||||
const renderedArrayItems = (): any[] => {
|
||||
const templates = arrayTemplates.value;
|
||||
// 多模板(variant):懒填 type/role 标识值到模板(幂等),保证展示与保存有标识值
|
||||
if (templates.length > 1) templates.forEach(autoFillVariant);
|
||||
return templates;
|
||||
};
|
||||
|
||||
// 原始值数组元素:值直接读写模板原始值对象上的 value
|
||||
const getTemplatePrimitive = (item: any): any => {
|
||||
if (!item || typeof item !== 'object') return '';
|
||||
return item.value !== undefined ? item.value : item.defaultValue ?? '';
|
||||
};
|
||||
|
||||
const setTemplatePrimitive = (item: any, v: any): void => {
|
||||
if (!item || typeof item !== 'object') return;
|
||||
item.value = v ?? '';
|
||||
};
|
||||
|
||||
// ===== array:联合数组(enumValues 多模板)→ 全部模板平铺,固定条数,不可增删 =====
|
||||
@@ -366,25 +353,6 @@ const autoFillVariant = (tpl: any): void => {
|
||||
}
|
||||
};
|
||||
|
||||
// 联合数组渲染条目:value 与 enumValues 模板按索引一一对应(懒补模板),保证固定条数
|
||||
const getVariantItems = (): any[] => {
|
||||
if (!isVariantArray.value || !def.value) return [];
|
||||
const templates = Array.isArray(def.value.enumValues) ? def.value.enumValues : [];
|
||||
if (!Array.isArray(def.value.value)) def.value.value = [];
|
||||
templates.forEach((tpl: any, i: number) => {
|
||||
const existing = def.value.value[i];
|
||||
if (!existing || typeof existing !== 'object') {
|
||||
const item = normalizeArrayItem(deepClone(tpl));
|
||||
autoFillVariant(item);
|
||||
def.value.value[i] = item;
|
||||
}
|
||||
});
|
||||
if (def.value.value.length > templates.length) {
|
||||
def.value.value = def.value.value.slice(0, templates.length);
|
||||
}
|
||||
return def.value.value;
|
||||
};
|
||||
|
||||
const variantLabel = (idx: number): string => templateLabel(def.value?.enumValues?.[idx], idx);
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user