Files
mixvideo-v2/apps/desktop/src/utils/error-handler.ts
imeepos bcfc9bb291 feat: 实现工作流表单字段与ComfyUI节点映射功能
主要功能:
- 实现UI字段与ComfyUI工作流节点的映射配置
- 添加节点映射编辑器组件(NodeMappingEditor)
- 实现工作流执行服务(WorkflowExecutionService)
- 添加工作流执行页面和结果展示组件
- 完善错误处理和用户反馈机制

修复问题:
- 修复滑块/数字输入最小值不能填0的问题
- 修复图片上传组件不可用的问题
- 修复React渲染对象错误(LayerMask问题)
- 添加拖拽上传功能和进度显示

技术改进:
- 支持0-1浮点数范围和步长配置
- 实现完整的文件上传流程(本地路径云端URL)
- 添加类型安全的节点映射配置
- 优化用户界面交互体验
2025-08-07 18:33:56 +08:00

287 lines
8.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 错误处理工具类
* 提供统一的错误处理和用户友好的错误消息
*/
export interface ErrorInfo {
code: string;
message: string;
details?: string;
suggestions?: string[];
}
export class ErrorHandler {
/**
* 解析Tauri命令错误
*/
static parseTauriError(error: any): ErrorInfo {
const errorStr = String(error);
// 工作流模板相关错误
if (errorStr.includes('工作流模板不存在')) {
return {
code: 'WORKFLOW_TEMPLATE_NOT_FOUND',
message: '工作流模板不存在',
details: '请确认工作流模板ID是否正确',
suggestions: [
'检查工作流模板是否已被删除',
'刷新页面重新加载模板列表',
'联系管理员确认模板状态'
]
};
}
// 输入数据验证错误
if (errorStr.includes('输入数据验证失败')) {
const details = errorStr.split('输入数据验证失败:')[1]?.trim();
return {
code: 'INPUT_VALIDATION_FAILED',
message: '输入数据验证失败',
details: details || '请检查输入的参数是否符合要求',
suggestions: [
'检查必填字段是否已填写',
'确认数值字段的取值范围',
'验证文本字段的格式要求',
'检查选择字段的选项是否正确'
]
};
}
// 节点映射错误
if (errorStr.includes('节点映射') || errorStr.includes('node mapping')) {
return {
code: 'NODE_MAPPING_ERROR',
message: '节点映射配置错误',
details: '工作流的节点映射配置有问题',
suggestions: [
'检查UI字段是否正确映射到ComfyUI节点',
'确认目标节点ID是否存在于工作流中',
'验证输入字段名称是否正确',
'检查数据转换类型是否匹配'
]
};
}
// ComfyUI连接错误
if (errorStr.includes('ComfyUI') && (errorStr.includes('连接') || errorStr.includes('connection'))) {
return {
code: 'COMFYUI_CONNECTION_ERROR',
message: 'ComfyUI服务连接失败',
details: '无法连接到ComfyUI服务器',
suggestions: [
'检查ComfyUI服务是否正在运行',
'确认ComfyUI服务器地址和端口配置',
'检查网络连接是否正常',
'查看ComfyUI服务器日志'
]
};
}
// 工作流执行错误
if (errorStr.includes('执行工作流失败') || errorStr.includes('workflow execution failed')) {
return {
code: 'WORKFLOW_EXECUTION_FAILED',
message: '工作流执行失败',
details: '工作流在执行过程中遇到错误',
suggestions: [
'检查输入参数是否正确',
'确认ComfyUI工作流配置是否有效',
'查看ComfyUI服务器日志获取详细错误信息',
'尝试使用默认参数重新执行'
]
};
}
// 数据库错误
if (errorStr.includes('数据库') || errorStr.includes('database')) {
return {
code: 'DATABASE_ERROR',
message: '数据库操作失败',
details: '数据库操作过程中发生错误',
suggestions: [
'检查数据库连接是否正常',
'确认数据库文件是否存在',
'尝试重启应用程序',
'检查磁盘空间是否充足'
]
};
}
// 文件系统错误
if (errorStr.includes('文件') || errorStr.includes('file') || errorStr.includes('路径') || errorStr.includes('path')) {
return {
code: 'FILE_SYSTEM_ERROR',
message: '文件系统操作失败',
details: '文件读取、写入或路径访问失败',
suggestions: [
'检查文件路径是否正确',
'确认文件是否存在',
'检查文件访问权限',
'确认磁盘空间是否充足'
]
};
}
// 网络错误
if (errorStr.includes('网络') || errorStr.includes('network') || errorStr.includes('timeout')) {
return {
code: 'NETWORK_ERROR',
message: '网络请求失败',
details: '网络连接或请求超时',
suggestions: [
'检查网络连接是否正常',
'确认服务器地址是否正确',
'尝试稍后重新请求',
'检查防火墙设置'
]
};
}
// 权限错误
if (errorStr.includes('权限') || errorStr.includes('permission') || errorStr.includes('access denied')) {
return {
code: 'PERMISSION_ERROR',
message: '权限不足',
details: '没有足够的权限执行此操作',
suggestions: [
'检查文件或目录的访问权限',
'尝试以管理员身份运行应用',
'确认用户账户权限设置',
'联系系统管理员'
]
};
}
// 默认错误
return {
code: 'UNKNOWN_ERROR',
message: '未知错误',
details: errorStr,
suggestions: [
'尝试重新执行操作',
'检查应用程序日志',
'重启应用程序',
'联系技术支持'
]
};
}
/**
* 格式化错误消息用于显示
*/
static formatErrorMessage(errorInfo: ErrorInfo): string {
let message = errorInfo.message;
if (errorInfo.details) {
message += `\n\n详细信息${errorInfo.details}`;
}
if (errorInfo.suggestions && errorInfo.suggestions.length > 0) {
message += '\n\n建议解决方案';
errorInfo.suggestions.forEach((suggestion, index) => {
message += `\n${index + 1}. ${suggestion}`;
});
}
return message;
}
/**
* 显示错误通知
*/
static showErrorNotification(error: any, title: string = '操作失败') {
const errorInfo = this.parseTauriError(error);
const message = this.formatErrorMessage(errorInfo);
// 这里可以集成具体的通知组件
console.error(`${title}:`, message);
// 如果有全局通知系统,可以在这里调用
// notificationService.error(title, message);
return errorInfo;
}
/**
* 检查是否为可重试的错误
*/
static isRetryableError(errorInfo: ErrorInfo): boolean {
const retryableCodes = [
'COMFYUI_CONNECTION_ERROR',
'NETWORK_ERROR',
'WORKFLOW_EXECUTION_FAILED'
];
return retryableCodes.includes(errorInfo.code);
}
/**
* 检查是否为用户输入错误
*/
static isUserInputError(errorInfo: ErrorInfo): boolean {
const userInputCodes = [
'INPUT_VALIDATION_FAILED',
'NODE_MAPPING_ERROR'
];
return userInputCodes.includes(errorInfo.code);
}
/**
* 获取错误的严重程度
*/
static getErrorSeverity(errorInfo: ErrorInfo): 'low' | 'medium' | 'high' | 'critical' {
switch (errorInfo.code) {
case 'INPUT_VALIDATION_FAILED':
case 'NODE_MAPPING_ERROR':
return 'low';
case 'COMFYUI_CONNECTION_ERROR':
case 'NETWORK_ERROR':
case 'WORKFLOW_EXECUTION_FAILED':
return 'medium';
case 'DATABASE_ERROR':
case 'FILE_SYSTEM_ERROR':
case 'PERMISSION_ERROR':
return 'high';
case 'WORKFLOW_TEMPLATE_NOT_FOUND':
case 'UNKNOWN_ERROR':
default:
return 'critical';
}
}
}
/**
* 错误边界组件的错误处理
*/
export const handleComponentError = (error: Error, errorInfo: any) => {
console.error('组件错误:', error, errorInfo);
// 可以在这里发送错误报告到监控服务
// errorReportingService.captureException(error, { extra: errorInfo });
};
/**
* Promise 错误处理装饰器
*/
export const withErrorHandling = <T extends (...args: any[]) => Promise<any>>(
fn: T,
errorHandler?: (error: any) => void
): T => {
return (async (...args: any[]) => {
try {
return await fn(...args);
} catch (error) {
if (errorHandler) {
errorHandler(error);
} else {
ErrorHandler.showErrorNotification(error);
}
throw error;
}
}) as T;
};