Files
ZenEcho b48e639490 feat: 引入共享类型与工具层,重构代码结构并优化用户体验
- 新增 `shared/` 目录,统一管理前后端共享的类型定义与工具函数,消除重复代码
- 重构 IPC 数据传输,使用 `toIpcSafeSnapshot` 确保序列化安全
- 新增系统托盘独立窗口 (`/tray` 路由) 与主窗口关闭行为设置,提升用户体验
- 优化 Sing-box 配置校验错误提示,增强可读性
- 修复订阅更新无新节点时的提示逻辑
- 更新项目依赖与构建配置,支持共享层路径别名 (`@shared`)
- 补充单元测试,完善国际化词条
2026-03-01 16:50:40 +08:00

66 lines
1.7 KiB
TypeScript
Raw Permalink 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.
/**
* 标准化节点类型字符串
*
* 统一前后端对节点类型的标识,合并了两端原有的逻辑。
*
* @param type - 原始节点类型
* @returns 标准化后的节点类型
*
* @example
* normalizeNodeType('ss') // 'shadowsocks'
* normalizeNodeType('socks5') // 'socks'
* normalizeNodeType('https') // 'http'
*/
export function normalizeNodeType(type: unknown): string {
const t = String(type ?? '').trim().toLowerCase()
if (t === 'ss' || t === 'shadowsocks') return 'shadowsocks'
if (t === 'socks5' || t === 'socks') return 'socks'
if (t === 'https' || t === 'http') return 'http'
return t
}
/**
* 检查字符串是否为有效的图标 URL
*
* 支持 http/https/file 协议及 data URI scheme。
*/
export function isIconUrl(value: string): boolean {
const v = value.trim()
return (
v.startsWith('http://') ||
v.startsWith('https://') ||
v.startsWith('file://') ||
v.startsWith('data:')
)
}
/**
* 安全解析 JSON 字符串
*
* 尝试解析 JSON,如果失败则返回默认值,避免抛出异常。
*/
export function safeJsonParse<T>(value: string, fallback: T): T {
try {
return JSON.parse(value) as T
} catch {
return fallback
}
}
/**
* 解析字符串数组
*
* 支持解析 JSON 数组字符串或逗号分隔的字符串。
*/
export function parseStringArray(value: string): string[] {
try {
const parsed = JSON.parse(value)
if (Array.isArray(parsed)) {
return parsed.map(v => String(v).trim()).filter(Boolean)
}
} catch {
// ignore
}
return value.split(/[,,]/).map(v => v.trim()).filter(Boolean)
}