模型参数约束透传:collectExposedFields 从 constraint 归一化 fieldConstraint 供首页表单校验
模板字段约束实际挂在 constraint 键(min/max/uploadRules 等),原读取 fieldConstraint 键导致模型勾选字段的约束丢失。新增 toFieldConstraint 归一化(min→minValue、max→maxValue、uploadRules/accept→fileTypes/maxFileSize/maxFileCount),并将格式分隔符统一为英文逗号,修复 wan 模型音频上传被误拦。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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<string, any> = {};
|
||||
// 数字 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 }
|
||||
|
||||
Reference in New Issue
Block a user