diff --git a/apps/desktop/src/components/comfyui/WorkflowTemplateCreator.tsx b/apps/desktop/src/components/comfyui/WorkflowTemplateCreator.tsx index 15e7661..8e65e53 100644 --- a/apps/desktop/src/components/comfyui/WorkflowTemplateCreator.tsx +++ b/apps/desktop/src/components/comfyui/WorkflowTemplateCreator.tsx @@ -28,16 +28,23 @@ interface TemplateMetadata { } interface ParameterSchema { - param_type: 'string' | 'number' | 'boolean' | 'array' | 'object'; + param_type: 'string' | 'number' | 'boolean' | 'array' | 'object' | 'image' | 'audio' | 'video' | 'integer' | 'float'; required?: boolean; default?: any; description?: string; enum?: any[]; min?: number; max?: number; + step?: number; pattern?: string; items?: ParameterSchema; properties?: Record; + // 媒体文件相关属性 + accept?: string; // 文件类型限制 + maxSize?: number; // 最大文件大小(字节) + width?: number; // 图片/视频宽度 + height?: number; // 图片/视频高度 + duration?: number; // 音频/视频时长限制 } interface WorkflowTemplateData { @@ -183,6 +190,61 @@ export const WorkflowTemplateCreator: React.FC = ( setNewParameterName(''); }; + // 根据参数类型获取默认配置 + const getDefaultConfigForType = (type: string): Partial => { + switch (type) { + case 'integer': + return { + default: 10, + min: 0, + max: 100, + step: 1, + }; + case 'float': + return { + default: 0.3, + min: 0.0, + max: 1.0, + step: 0.01, + }; + case 'image': + return { + default: '', + accept: '.jpg,.jpeg,.png,.webp,.bmp,.tiff', + maxSize: 10 * 1024 * 1024, // 10MB + description: '支持的图片格式:JPG, PNG, WebP, BMP, TIFF', + }; + case 'audio': + return { + default: '', + accept: '.mp3,.wav,.flac,.aac,.ogg', + maxSize: 50 * 1024 * 1024, // 50MB + description: '支持的音频格式:MP3, WAV, FLAC, AAC, OGG', + }; + case 'video': + return { + default: '', + accept: '.mp4,.avi,.mov,.mkv,.webm', + maxSize: 500 * 1024 * 1024, // 500MB + description: '支持的视频格式:MP4, AVI, MOV, MKV, WebM', + }; + case 'boolean': + return { + default: false, + }; + case 'number': + return { + default: 0, + min: 0, + max: 100, + }; + default: + return { + default: '', + }; + } + }; + // 验证表单 const validateForm = (): boolean => { const newErrors: Record = {}; @@ -567,17 +629,33 @@ export const WorkflowTemplateCreator: React.FC = ( @@ -585,16 +663,60 @@ export const WorkflowTemplateCreator: React.FC = ( - updateParameter(paramName, { - ...schema, - default: schema.param_type === 'number' ? Number(e.target.value) : e.target.value - })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" - placeholder="设置默认值" - /> + {schema.param_type === 'boolean' ? ( + + ) : schema.param_type === 'integer' || schema.param_type === 'float' || schema.param_type === 'number' ? ( + updateParameter(paramName, { + ...schema, + default: schema.param_type === 'integer' ? parseInt(e.target.value) || 0 : parseFloat(e.target.value) || 0 + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="设置默认值" + /> + ) : schema.param_type === 'image' || schema.param_type === 'audio' || schema.param_type === 'video' ? ( +
+ updateParameter(paramName, { + ...schema, + default: e.target.value + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="默认文件名或路径" + /> +

+ 支持格式: {schema.accept || '所有格式'} +

+
+ ) : ( + updateParameter(paramName, { + ...schema, + default: e.target.value + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="设置默认值" + /> + )}
@@ -628,14 +750,15 @@ export const WorkflowTemplateCreator: React.FC = (
- {schema.param_type === 'number' && ( -
+ {(schema.param_type === 'number' || schema.param_type === 'integer' || schema.param_type === 'float') && ( +
updateParameter(paramName, { ...schema, @@ -651,6 +774,7 @@ export const WorkflowTemplateCreator: React.FC = ( updateParameter(paramName, { ...schema, @@ -660,6 +784,112 @@ export const WorkflowTemplateCreator: React.FC = ( placeholder="最大值" />
+
+ + updateParameter(paramName, { + ...schema, + step: e.target.value ? Number(e.target.value) : undefined + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder={schema.param_type === 'float' ? '0.01' : '1'} + /> +
+
+ )} + + {(schema.param_type === 'image' || schema.param_type === 'audio' || schema.param_type === 'video') && ( +
+
+
+ + updateParameter(paramName, { + ...schema, + accept: e.target.value + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder=".jpg,.png,.webp" + /> +
+
+ + updateParameter(paramName, { + ...schema, + maxSize: e.target.value ? Number(e.target.value) * 1024 * 1024 : undefined + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="10" + /> +
+
+ + {(schema.param_type === 'image' || schema.param_type === 'video') && ( +
+
+ + updateParameter(paramName, { + ...schema, + width: e.target.value ? Number(e.target.value) : undefined + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="1920" + /> +
+
+ + updateParameter(paramName, { + ...schema, + height: e.target.value ? Number(e.target.value) : undefined + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="1080" + /> +
+
+ )} + + {(schema.param_type === 'audio' || schema.param_type === 'video') && ( +
+ + updateParameter(paramName, { + ...schema, + duration: e.target.value ? Number(e.target.value) : undefined + })} + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + placeholder="300" + /> +
+ )}
)}