/** * 下载错误代码和消息定义 * 统一管理所有下载相关的错误提示 */ export enum DownloadErrorCode { // 权限相关 UNAUTHORIZED = 'UNAUTHORIZED', FORBIDDEN = 'FORBIDDEN', NO_PERMISSION = 'NO_PERMISSION', VIDEO_WAIT_PERIOD = 'VIDEO_WAIT_PERIOD', // 文件不存在 MATERIAL_NOT_FOUND = 'MATERIAL_NOT_FOUND', FILE_NOT_FOUND = 'FILE_NOT_FOUND', FILE_MISSING = 'FILE_MISSING', // 新增:源文件缺失(明确标识) PSD_NOT_FOUND = 'PSD_NOT_FOUND', NO_DOWNLOADABLE_FILES = 'NO_DOWNLOADABLE_FILES', // 网络/存储 S3_ACCESS_FAILED = 'S3_ACCESS_FAILED', NETWORK_ERROR = 'NETWORK_ERROR', FILE_READ_ERROR = 'FILE_READ_ERROR', // 数据错误 INVALID_DOWNLOAD_TYPE = 'INVALID_DOWNLOAD_TYPE', ASSET_TYPE_MISMATCH = 'ASSET_TYPE_MISMATCH', BIGINT_SERIALIZATION_ERROR = 'BIGINT_SERIALIZATION_ERROR', // 处理错误 ZIP_CREATION_FAILED = 'ZIP_CREATION_FAILED', STREAM_ERROR = 'STREAM_ERROR', UNKNOWN_ERROR = 'UNKNOWN_ERROR', } /** * 错误消息映射(中文) */ export const DownloadErrorMessages: Record = { [DownloadErrorCode.UNAUTHORIZED]: '请先登录', [DownloadErrorCode.FORBIDDEN]: '您的下载权限已被限制,请联系管理员', [DownloadErrorCode.NO_PERMISSION]: '无权限下载该素材', [DownloadErrorCode.VIDEO_WAIT_PERIOD]: '视频类素材上传后满 15 天才能下载', [DownloadErrorCode.MATERIAL_NOT_FOUND]: '素材不存在', [DownloadErrorCode.FILE_NOT_FOUND]: '源文件已丢失(可能被清空),可尝试下载预览图', [DownloadErrorCode.FILE_MISSING]: '没有源文件,可联系作者重新上传', [DownloadErrorCode.PSD_NOT_FOUND]: 'PSD 文件不存在', [DownloadErrorCode.NO_DOWNLOADABLE_FILES]: '没有可下载的文件', [DownloadErrorCode.S3_ACCESS_FAILED]: '存储服务访问失败,请稍后重试', [DownloadErrorCode.NETWORK_ERROR]: '网络连接失败,请检查网络后重试', [DownloadErrorCode.FILE_READ_ERROR]: '文件读取失败,请稍后重试', [DownloadErrorCode.INVALID_DOWNLOAD_TYPE]: '无效的下载类型', [DownloadErrorCode.ASSET_TYPE_MISMATCH]: '文件类型不匹配,请联系管理员', [DownloadErrorCode.BIGINT_SERIALIZATION_ERROR]: '数据处理错误,请稍后重试', [DownloadErrorCode.ZIP_CREATION_FAILED]: '文件打包失败,请稍后重试', [DownloadErrorCode.STREAM_ERROR]: '文件流读取失败,请稍后重试', [DownloadErrorCode.UNKNOWN_ERROR]: '下载失败,请稍后重试', }; /** * 下载错误响应接口 */ export interface DownloadErrorResponse { error: string; code?: DownloadErrorCode; details?: string; } /** * 创建标准化的错误响应 */ export function createDownloadError( code: DownloadErrorCode, details?: string ): DownloadErrorResponse { return { error: DownloadErrorMessages[code], code, ...(details && { details }), }; } /** * 根据错误代码获取用户友好的错误消息 */ export function getDownloadErrorMessage(code?: DownloadErrorCode | string): string { if (!code) { return DownloadErrorMessages[DownloadErrorCode.UNKNOWN_ERROR]; } // 如果是字符串,尝试转换为枚举 const errorCode = Object.values(DownloadErrorCode).includes(code as DownloadErrorCode) ? (code as DownloadErrorCode) : DownloadErrorCode.UNKNOWN_ERROR; return DownloadErrorMessages[errorCode as DownloadErrorCode] || DownloadErrorMessages[DownloadErrorCode.UNKNOWN_ERROR]; } /** * 从错误对象中提取错误代码和消息 */ export function parseDownloadError(error: any): { code: DownloadErrorCode; message: string; details?: string; } { // 如果已经是标准化的错误响应 if (error?.code && Object.values(DownloadErrorCode).includes(error.code as DownloadErrorCode)) { const code = error.code as DownloadErrorCode; return { code, message: code === DownloadErrorCode.VIDEO_WAIT_PERIOD ? error.details || error.error || DownloadErrorMessages[code] : error.error || DownloadErrorMessages[code], details: error.details, }; } // 如果是字符串错误消息,尝试匹配错误代码 const errorMessage = error?.error || error?.message || String(error); // 根据错误消息内容推断错误类型 // 优先检查更具体的错误类型 if (errorMessage.includes('没有源文件') || errorMessage.includes('源文件缺失') || errorMessage.includes('联系作者')) { return { code: DownloadErrorCode.FILE_MISSING, message: DownloadErrorMessages[DownloadErrorCode.FILE_MISSING] }; } if (errorMessage.includes('未登录') || errorMessage.includes('请先登录')) { return { code: DownloadErrorCode.UNAUTHORIZED, message: DownloadErrorMessages[DownloadErrorCode.UNAUTHORIZED] }; } if (errorMessage.includes('权限') || errorMessage.includes('无权限')) { return { code: DownloadErrorCode.NO_PERMISSION, message: DownloadErrorMessages[DownloadErrorCode.NO_PERMISSION] }; } if (errorMessage.includes('满 15 天') || errorMessage.includes('上传后')) { return { code: DownloadErrorCode.VIDEO_WAIT_PERIOD, message: DownloadErrorMessages[DownloadErrorCode.VIDEO_WAIT_PERIOD], details: error?.details }; } if (errorMessage.includes('不存在') || errorMessage.includes('not found')) { return { code: DownloadErrorCode.FILE_NOT_FOUND, message: DownloadErrorMessages[DownloadErrorCode.FILE_NOT_FOUND] }; } if (errorMessage.includes('S3') || errorMessage.includes('存储')) { return { code: DownloadErrorCode.S3_ACCESS_FAILED, message: DownloadErrorMessages[DownloadErrorCode.S3_ACCESS_FAILED] }; } if (errorMessage.includes('网络') || errorMessage.includes('network')) { return { code: DownloadErrorCode.NETWORK_ERROR, message: DownloadErrorMessages[DownloadErrorCode.NETWORK_ERROR] }; } if (errorMessage.includes('BigInt')) { return { code: DownloadErrorCode.BIGINT_SERIALIZATION_ERROR, message: DownloadErrorMessages[DownloadErrorCode.BIGINT_SERIALIZATION_ERROR] }; } // 默认未知错误 return { code: DownloadErrorCode.UNKNOWN_ERROR, message: errorMessage || DownloadErrorMessages[DownloadErrorCode.UNKNOWN_ERROR], }; }