import { RunFormSchema, FormFieldSchema } from '@/lib/types/template-run'; // 定义工作流节点的数据结构 interface WorkflowNode { id: string; type: 'image' | 'video' | 'text' | 'audio'; data: { label: string; description?: string; flowType: 'start' | 'normal' | 'end'; actionData?: { prompt?: string; aspectRatio?: string; selectedModel?: string; duration?: string; advancedParams?: Record; }; output?: { images?: Array<{ url: string }>; videos?: Array<{ url: string }>; coverUrl?: string; }; }; } interface FormSchemaData { startNodes: WorkflowNode[]; endNodes: WorkflowNode[]; } // 节点类型到表单字段类型的映射 const nodeTypeToFieldType = { image: 'image', video: 'video', text: 'textarea', audio: 'text', // 暂时用文本字段处理音频 }; // 生成字段名称 const generateFieldName = (node: WorkflowNode, index: number): string => { const typePrefix = node.type; const flowType = node.data.flowType; return `${typePrefix}_${flowType}_${index}`; }; // 生成字段标签 const generateFieldLabel = (node: WorkflowNode): string => { const baseLabel = node.data.label || `节点 ${node.id.slice(-8)}`; const flowTypeLabel = { start: '(输入)', normal: '(处理)', end: '(输出)' }; return baseLabel + (flowTypeLabel[node.data.flowType] || ''); }; // 转换单个节点为表单字段 const transformNodeToFormField = (node: WorkflowNode, index: number): FormFieldSchema | null => { // 只为start节点生成表单字段,因为用户只需要输入数据 if (node.data.flowType !== 'start') { return null; } const fieldName = generateFieldName(node, index); const fieldType = nodeTypeToFieldType[node.type] || 'text'; const fieldLabel = generateFieldLabel(node); const field: FormFieldSchema = { name: fieldName, label: fieldLabel, type: fieldType as any, required: true, description: node.data.description || `请上传${node.type === 'image' ? '图片' : node.type === 'video' ? '视频' : '内容'}`, }; // 根据节点类型设置默认值和占位符 switch (node.type) { case 'image': field.placeholder = '点击上传图片'; if (node.data.output?.coverUrl) { field.defaultValue = node.data.output.coverUrl; } break; case 'video': field.placeholder = '点击上传视频'; if (node.data.output?.videos?.[0]?.url) { field.defaultValue = node.data.output.videos[0].url; } break; case 'text': field.placeholder = '请输入文本内容'; field.min = 1; field.max = 1000; break; } // 如果节点有预填的prompt,作为提示信息 if (node.data.actionData?.prompt) { field.description += `\n\n提示:${node.data.actionData.prompt}`; } return field; }; // 主要的转换函数 export function transformWorkflowToFormSchema(formSchemaData: unknown): RunFormSchema { try { // 类型守卫:检查数据格式 if (!formSchemaData || typeof formSchemaData !== 'object') { console.warn('formSchema数据格式无效'); return { fields: [] }; } const data = formSchemaData as any; // 检查是否包含nodes数组(新格式)或startNodes/endNodes(旧格式) let nodesToProcess: WorkflowNode[] = []; if (Array.isArray(data.nodes)) { // 新格式:从nodes数组中筛选start节点 nodesToProcess = data.nodes.filter((node: any) => node.data?.flowType === 'start' ); } else if (Array.isArray(data.startNodes)) { // 旧格式:使用startNodes nodesToProcess = data.startNodes; } if (nodesToProcess.length === 0) { console.log('未找到需要用户输入的节点'); return { fields: [] }; } // 转换节点为表单字段 const fields: FormFieldSchema[] = []; nodesToProcess.forEach((node: any, index: number) => { const formField = transformNodeToFormField(node, index); if (formField) { fields.push(formField); } }); console.log(`成功转换 ${fields.length} 个表单字段`); return { fields, validation: {} }; } catch (error) { console.error('转换formSchema失败:', error); return { fields: [] }; } } // 验证转换后的表单配置 export function validateFormSchema(schema: RunFormSchema): boolean { if (!schema || !Array.isArray(schema.fields)) { return false; } return schema.fields.every(field => { return ( field.name && field.label && field.type && ['text', 'number', 'textarea', 'select', 'image', 'video', 'color'].includes(field.type) ); }); }