- 创建统一的下载错误处理模块 (lib/download-errors.ts) - 实现13种错误类型分类和中文错误消息 - 后端统一使用 createDownloadError 创建标准化错误响应 - 前端统一使用 parseDownloadError 解析错误并显示 - 修复正式系统数据库Schema,添加产品全案相关字段和表 - 执行数据库迁移:添加 task_no, task_status, task_fetched_at 字段 - 创建 material_assets, api_keys, api_call_logs 表
146 lines
5.1 KiB
TypeScript
146 lines
5.1 KiB
TypeScript
/**
|
|
* 下载错误代码和消息定义
|
|
* 统一管理所有下载相关的错误提示
|
|
*/
|
|
|
|
export enum DownloadErrorCode {
|
|
// 权限相关
|
|
UNAUTHORIZED = 'UNAUTHORIZED',
|
|
FORBIDDEN = 'FORBIDDEN',
|
|
NO_PERMISSION = 'NO_PERMISSION',
|
|
|
|
// 文件不存在
|
|
MATERIAL_NOT_FOUND = 'MATERIAL_NOT_FOUND',
|
|
FILE_NOT_FOUND = 'FILE_NOT_FOUND',
|
|
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.MATERIAL_NOT_FOUND]: '素材不存在',
|
|
[DownloadErrorCode.FILE_NOT_FOUND]: '文件不存在或已被删除',
|
|
[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: error.error || DownloadErrorMessages[code],
|
|
details: error.details,
|
|
};
|
|
}
|
|
|
|
// 如果是字符串错误消息,尝试匹配错误代码
|
|
const errorMessage = error?.error || error?.message || String(error);
|
|
|
|
// 根据错误消息内容推断错误类型
|
|
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('不存在') || 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],
|
|
};
|
|
}
|