mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-06-16 13:34:04 +08:00
de7f93d513
- Replace complex gradient animations with clean, minimal tab design - Migrate from @lobehub/icons CDN to local SVG assets for better reliability - Fix clippy warning in error.rs (use inline format args) - Improve code formatting in skill service and commands - Reduce CSS complexity in AppSwitcher component (removed blur effects and gradients) - Update BrandIcons to use imported local SVG files instead of dynamic image loading This improves performance, reduces external dependencies, and provides a cleaner UI experience.
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
import { TFunction } from "i18next";
|
||
|
||
/**
|
||
* 结构化错误对象
|
||
*/
|
||
export interface SkillError {
|
||
code: string;
|
||
context: Record<string, string>;
|
||
suggestion?: string;
|
||
}
|
||
|
||
/**
|
||
* 尝试解析后端返回的错误字符串
|
||
* 如果是 JSON 格式,返回结构化错误;否则返回 null
|
||
*/
|
||
export function parseSkillError(errorString: string): SkillError | null {
|
||
try {
|
||
const parsed = JSON.parse(errorString);
|
||
if (parsed.code && parsed.context) {
|
||
return parsed as SkillError;
|
||
}
|
||
} catch {
|
||
// 不是 JSON 格式,返回 null
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 将错误码映射到 i18n key
|
||
*/
|
||
function getErrorI18nKey(code: string): string {
|
||
const mapping: Record<string, string> = {
|
||
SKILL_NOT_FOUND: "skills.error.skillNotFound",
|
||
MISSING_REPO_INFO: "skills.error.missingRepoInfo",
|
||
DOWNLOAD_TIMEOUT: "skills.error.downloadTimeout",
|
||
DOWNLOAD_FAILED: "skills.error.downloadFailed",
|
||
SKILL_DIR_NOT_FOUND: "skills.error.skillDirNotFound",
|
||
EMPTY_ARCHIVE: "skills.error.emptyArchive",
|
||
GET_HOME_DIR_FAILED: "skills.error.getHomeDirFailed",
|
||
};
|
||
|
||
return mapping[code] || "skills.error.unknownError";
|
||
}
|
||
|
||
/**
|
||
* 将建议码映射到 i18n key
|
||
*/
|
||
function getSuggestionI18nKey(suggestion: string): string {
|
||
const mapping: Record<string, string> = {
|
||
checkNetwork: "skills.error.suggestion.checkNetwork",
|
||
checkProxy: "skills.error.suggestion.checkProxy",
|
||
retryLater: "skills.error.suggestion.retryLater",
|
||
checkRepoUrl: "skills.error.suggestion.checkRepoUrl",
|
||
checkPermission: "skills.error.suggestion.checkPermission",
|
||
http403: "skills.error.http403",
|
||
http404: "skills.error.http404",
|
||
http429: "skills.error.http429",
|
||
};
|
||
|
||
return mapping[suggestion] || suggestion;
|
||
}
|
||
|
||
/**
|
||
* 格式化技能错误为用户友好的消息
|
||
* @param errorString 后端返回的错误字符串
|
||
* @param t i18next 翻译函数
|
||
* @param defaultTitle 默认标题的 i18n key(如 "skills.installFailed")
|
||
* @returns 包含标题和描述的对象
|
||
*/
|
||
export function formatSkillError(
|
||
errorString: string,
|
||
t: TFunction,
|
||
defaultTitle: string = "skills.installFailed",
|
||
): { title: string; description: string } {
|
||
const parsedError = parseSkillError(errorString);
|
||
|
||
if (!parsedError) {
|
||
// 如果不是结构化错误,返回原始错误字符串
|
||
return {
|
||
title: t(defaultTitle),
|
||
description: errorString || t("common.error"),
|
||
};
|
||
}
|
||
|
||
const { code, context, suggestion } = parsedError;
|
||
|
||
// 获取错误消息的 i18n key
|
||
const errorKey = getErrorI18nKey(code);
|
||
|
||
// 构建描述(错误消息 + 建议)
|
||
let description = t(errorKey, context);
|
||
|
||
// 如果有建议,追加到描述中
|
||
if (suggestion) {
|
||
const suggestionKey = getSuggestionI18nKey(suggestion);
|
||
const suggestionText = t(suggestionKey);
|
||
description += `\n\n${suggestionText}`;
|
||
}
|
||
|
||
return {
|
||
title: t(defaultTitle),
|
||
description,
|
||
};
|
||
}
|