首页工作流:输出字段中文展示 + 引用面板滚动修复

- valueSource 契约统一为 { nodeId, field },替换 modelParamUtils 中 fieldName 旧用法
- 数组模板压缩时记录 __originIndex,叶子字段扁平清单按后端原始索引产出 enumValues
- 模型节点输出项保存时用 responseMapping 中文填充 value,引用展示显示中文
- http 节点输出字段识别 JsonEditor 包裹结构,修正真实数据路径并提取中文 label
- 引用上级节点输出面板超高时内部滚动,避免超出视口被截掉

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-19 17:07:21 +08:00
co-authored by Claude
parent c8f457dada
commit f7b3531392
5 changed files with 235 additions and 42 deletions
@@ -76,7 +76,7 @@
import { ref, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import ModelSelector from '/@/views/settings/workflow/component/ModelSelector.vue';
import { stripReadonlyFields, deepClone } from '/@/views/settings/workflow/component/modelParamUtils';
import { stripReadonlyFields, deepClone, buildModelRequestParamsPath, enrichResponseBodyMapping } from '/@/views/settings/workflow/component/modelParamUtils';
import { getWorkflowDetail, saveWorkflow } from '/@/api/settings/creation';
import { getModelManage, updateModelManage } from '/@/api/settings/modelConfigV2';
@@ -109,6 +109,13 @@ const systemModelNodeIds = ref<Record<string, boolean>>({});
const modelNodes = computed(() => nodes.value.filter((n) => String(n?.nodeCode || '').toLowerCase() === 'model'));
// 开始节点 id:模板 DSL 与工作流管理 DSL 结构一致(nodeCode === '__start__'),
// 供 buildModelRequestParamsPath 为「表单展示」字段补 valueSource 指向开始节点
const getStartNodeId = () => {
const sn = nodes.value.find((n) => String(n?.nodeCode || '').toLowerCase() === '__start__');
return sn?.id || '';
};
const canSave = computed(() => {
if (!flowName.value.trim()) return false;
// 所有模型节点都必须已绑定模型
@@ -162,9 +169,13 @@ const handleModelConfirm = (model: any) => {
node.modelConfig.modelId = model.id || '';
node.modelConfig.modelName = model.modelName;
node.modelConfig.modelType = model.modelType;
// 深拷贝模型 requestBodyMapping 作为参数模板,剔除只读字段
node.modelConfig.modelRequestParams = stripReadonlyFields(deepClone(model.requestBodyMapping ?? null));
node.modelConfig.modelResponseBodyMapping = model.responseBodyMapping ?? null;
// 深拷贝模型 requestBodyMapping 作为参数模板,剔除只读字段(strip 会给被压缩的数组模板记 __originIndex
const params = stripReadonlyFields(deepClone(model.requestBodyMapping ?? null));
node.modelConfig.modelRequestParams = params;
// 后端契约:基于编辑器参数树(含 __originIndex 原始索引)生成全部叶子字段扁平清单,与工作流管理保存一致
node.modelConfig.modelRequestParamsPath = buildModelRequestParamsPath(params, getStartNodeId());
// 用模型 responseMapping 的中文描述填充 value,供工作流管理「引用上级节点输出」展示中文
node.modelConfig.modelResponseBodyMapping = enrichResponseBodyMapping(model.responseBodyMapping, model.responseMapping);
// 选中为用户模型,无需再补 API Key
systemModelNodeIds.value[node.id] = false;
apiKeyInputs.value[node.id] = '';
@@ -249,6 +260,14 @@ const handleSave = async () => {
for (const node of modelNodes.value.filter((n) => systemModelNodeIds.value[n.id])) {
await convertSystemModel(node);
}
// 模板 DSL 若缺 modelRequestParamsPath(旧版模板),用现有参数树兜底生成,保证后端拿到契约字段
const startNodeId = getStartNodeId();
for (const node of modelNodes.value) {
const mc = node?.modelConfig;
if (mc?.modelRequestParams && !mc.modelRequestParamsPath) {
mc.modelRequestParamsPath = buildModelRequestParamsPath(mc.modelRequestParams, startNodeId);
}
}
const flowContent = {
...(templateFlowContent.value || {}),
nodes: nodes.value,