From 63ac39cd4add8ab2579b4cfdeb92268573a07755 Mon Sep 17 00:00:00 2001 From: 2910410219 <2910410219@qq.com> Date: Thu, 20 Aug 2026 11:46:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=8F=82=E6=95=B0=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=E9=80=8F=E4=BC=A0=EF=BC=9AcollectExposedFields=20?= =?UTF-8?q?=E4=BB=8E=20constraint=20=E5=BD=92=E4=B8=80=E5=8C=96=20fieldCon?= =?UTF-8?q?straint=20=E4=BE=9B=E9=A6=96=E9=A1=B5=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 模板字段约束实际挂在 constraint 键(min/max/uploadRules 等),原读取 fieldConstraint 键导致模型勾选字段的约束丢失。新增 toFieldConstraint 归一化(min→minValue、max→maxValue、uploadRules/accept→fileTypes/maxFileSize/maxFileCount),并将格式分隔符统一为英文逗号,修复 wan 模型音频上传被误拦。 Co-Authored-By: Claude --- .../workflow/component/modelParamUtils.ts | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/views/settings/workflow/component/modelParamUtils.ts b/src/views/settings/workflow/component/modelParamUtils.ts index 28cf8f0..4b944e6 100644 --- a/src/views/settings/workflow/component/modelParamUtils.ts +++ b/src/views/settings/workflow/component/modelParamUtils.ts @@ -193,6 +193,35 @@ export interface ExposedField { refNodeId?: string; // 预留:引用其他节点功能(后续启用) } +// 将模型模板字段级约束(constraint,JsonEditor 风格:min/max/uploadRules/accept/maxSize/maxCount 等) +// 归一化为首页运行表单消费的 fieldConstraint(minValue/maxValue/fileTypes/maxFileSize/maxFileCount)。 +// 模板字段约束实际挂在 constraint 键下(如 video_url.url 的 uploadRules、duration 的 min/numberType), +// 与 collectExposedFields 原读取的 fieldConstraint 键不一致,需在此转换后随 modelFormFields 透传首页。 +function toFieldConstraint(constraint: any): any { + if (!constraint || typeof constraint !== 'object') return undefined; + const out: Record = {}; + // 数字 min/max → 首页 el-input-number 的 minValue/maxValue + if (constraint.min !== undefined && constraint.min !== null) out.minValue = constraint.min; + if (constraint.max !== undefined && constraint.max !== null) out.maxValue = constraint.max; + // 上传约束:uploadRules 数组取第一条;兼容顶层 accept/maxSize/maxCount 单值形式 + const rules = Array.isArray(constraint.uploadRules) ? constraint.uploadRules.filter((r: any) => r && typeof r === 'object') : []; + const rule = rules[0] || null; + const fileTypes = rule?.format ?? constraint.accept; + if (fileTypes !== undefined && fileTypes !== null && fileTypes !== '') { + // 模板 format 可能用中文顿号/空白分隔(如 wan 模型 "wav、mp3"), + // 统一转英文逗号,保证首页 split(',') 与扩展名匹配正确 + out.fileTypes = String(fileTypes) + .replace(/[、\s]+/g, ',') + .replace(/,+/g, ',') + .replace(/^,|,$/g, ''); + } + const maxSize = rule?.maxSize ?? constraint.maxSize; + if (maxSize !== undefined && maxSize !== null) out.maxFileSize = maxSize; + const maxCount = rule?.maxCount ?? constraint.maxCount; + if (maxCount !== undefined && maxCount !== null) out.maxFileCount = maxCount; + return Object.keys(out).length > 0 ? out : undefined; +} + // 收集 runtimeShow === true 的叶子字段,生成暴露清单 // 路径文法(与 restoreRuntimeShow 共用): // object 子字段 → 父路径 + ".attrs." + 子key @@ -234,7 +263,10 @@ export function collectExposedFields(params: any, prefix = ''): ExposedField[] { options: Array.isArray(def.options) ? def.options : undefined, value: def.value, defaultValue: def.defaultValue, - fieldConstraint: def.fieldConstraint && typeof def.fieldConstraint === 'object' ? def.fieldConstraint : undefined, + // 优先透传已有的 fieldConstraint(首页格式);模板字段约束在 constraint 键时归一化补全 + fieldConstraint: + (def.fieldConstraint && typeof def.fieldConstraint === 'object' ? def.fieldConstraint : undefined) ?? + toFieldConstraint(def.constraint), valueSource: (() => { const vs = def.valueSource; // 契约统一数组;兼容旧 DSL 单对象 { nodeId, field }