gongxiangp2/lib/download-errors.ts
2026-05-25 10:39:26 +08:00

160 lines
6.1 KiB
TypeScript

/**
* 下载错误代码和消息定义
* 统一管理所有下载相关的错误提示
*/
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, string> = {
[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],
};
}